From 4fdcc718f95f2b4d3152f7b3a33a32c40cc0ed59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 21 Dec 2024 21:36:23 +0900 Subject: [PATCH 01/61] =?UTF-8?q?feat:=20=EC=A0=95=EA=B7=9C=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=20=EC=83=9D=EC=84=B1=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TimetableLectureApiV3.java | 40 +++++ .../TimetableLectureControllerV3.java | 31 ++++ .../TimetableRegularLectureCreateRequest.java | 30 ++++ .../response/TimetableLectureResponseV3.java | 143 ++++++++++++++++++ .../repository/LectureRepositoryV3.java | 18 +++ .../TimetableFrameRepositoryV3.java | 21 +++ .../TimetableLectureRepositoryV3.java | 9 ++ .../service/TimetableLectureServiceV3.java | 47 ++++++ 8 files changed, 339 insertions(+) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureCreateRequest.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableFrameRepositoryV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java new file mode 100644 index 0000000000..eb98d856a7 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java @@ -0,0 +1,40 @@ +package in.koreatech.koin.domain.timetableV3.controller; + +import static in.koreatech.koin.domain.user.model.UserType.STUDENT; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import in.koreatech.koin.global.auth.Auth; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; + +@Tag(name = "(Normal) Timetable: V3-시간표", description = "시간표 강의 정보를 관리한다") +public interface TimetableLectureApiV3 { + + @ApiResponses( + value = { + @ApiResponse(responseCode = "201"), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) + } + ) + @Operation(summary = "정규 강의 생성") + @SecurityRequirement(name = "Jwt Authentication") + @PostMapping("/v3/timetables/lecture/regular") + ResponseEntity createTimetablesRegularLecture( + @Valid @RequestBody TimetableRegularLectureCreateRequest request, + @Auth(permit = {STUDENT}) Integer userId + ); + +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java new file mode 100644 index 0000000000..354b8a4994 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java @@ -0,0 +1,31 @@ +package in.koreatech.koin.domain.timetableV3.controller; + +import static in.koreatech.koin.domain.user.model.UserType.STUDENT; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import in.koreatech.koin.domain.timetableV3.service.TimetableLectureServiceV3; +import in.koreatech.koin.global.auth.Auth; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class TimetableLectureControllerV3 { + + private final TimetableLectureServiceV3 timetableLectureV3; + + @PostMapping("/v3/timetables/lecture/regular") + ResponseEntity createTimetablesRegularLecture( + @Valid @RequestBody TimetableRegularLectureCreateRequest request, + @Auth(permit = {STUDENT}) Integer userId + ) { + TimetableLectureResponseV3 response = timetableLectureV3.createTimetablesRegularLecture(request, userId); + return ResponseEntity.ok(response); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureCreateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureCreateRequest.java new file mode 100644 index 0000000000..01d5d25e56 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureCreateRequest.java @@ -0,0 +1,30 @@ +package in.koreatech.koin.domain.timetableV3.dto.request; + +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; + +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import in.koreatech.koin.domain.timetable.model.Lecture; +import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; + +@JsonNaming(value = SnakeCaseStrategy.class) +public record TimetableRegularLectureCreateRequest( + @NotNull(message = "시간표 프레임 id를 입력해주세요.") + @Schema(description = "시간표 프레임 id", example = "1004", requiredMode = REQUIRED) + Integer timetableFrameId, + + @NotNull(message = "정규 강의 id를 입력해주세요.") + @Schema(description = "정규 강의 id", example = "3015", requiredMode = REQUIRED) + Integer lectureId +) { + public TimetableLecture toTimetableLecture(TimetableFrame frame, Lecture lecture) { + return TimetableLecture.builder() + .lecture(lecture) + .timetableFrame(frame) + .build(); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java new file mode 100644 index 0000000000..ca99e89f23 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java @@ -0,0 +1,143 @@ +package in.koreatech.koin.domain.timetableV3.dto.response; + +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import in.koreatech.koin.domain.timetable.model.Lecture; +import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import io.swagger.v3.oas.annotations.media.Schema; + +@JsonNaming(value = SnakeCaseStrategy.class) +public record TimetableLectureResponseV3( + @Schema(description = "시간표 프레임 id", example = "1") + Integer timetableFrameId, + + @Schema(description = "시간표 프레임 강의 정보") + List timetable, + + @Schema(description = "해당 학기 학점", example = "24") + Integer grades, + + @Schema(description = "전체 학기 학점", example = "131") + Integer totalGrades +) { + @JsonNaming(value = SnakeCaseStrategy.class) + public record InnerTimetableLectureResponseV3( + @Schema(description = "시간표 id", example = "1", requiredMode = REQUIRED) + Integer id, + + @Schema(description = "강의 id", example = "1", requiredMode = NOT_REQUIRED) + Integer lectureId, + + @Schema(description = "수강 정원", example = "38", requiredMode = NOT_REQUIRED) + String regularNumber, + + @Schema(description = "과목 코드", example = "ARB244", requiredMode = NOT_REQUIRED) + String code, + + @Schema(description = "설계 학점", example = "0", requiredMode = NOT_REQUIRED) + String designScore, + + @Schema(description = "강의 정보", requiredMode = NOT_REQUIRED) + List lectureInfos, + + @Schema(description = "메모", example = "null", requiredMode = NOT_REQUIRED) + String memo, + + @Schema(description = "학점", example = "3", requiredMode = REQUIRED) + String grades, + + @Schema(description = "강의(커스텀) 이름", example = "한국사", requiredMode = REQUIRED) + String classTitle, + + @Schema(description = "분반", example = "01", requiredMode = NOT_REQUIRED) + String lectureClass, + + @Schema(description = "대상", example = "디자 1 건축", requiredMode = NOT_REQUIRED) + String target, + + @Schema(description = "강의 교수", example = "이돈우", requiredMode = NOT_REQUIRED) + String professor, + + @Schema(description = "학부", example = "디자인ㆍ건축공학부", requiredMode = NOT_REQUIRED) + String department + ) { + @JsonNaming(value = SnakeCaseStrategy.class) + public record LectureInfo( + @Schema(description = "요일 id", example = "0", requiredMode = REQUIRED) + Integer week, + + @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) + Integer startTime, + + @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) + Integer endTime, + + @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) + String place + ) { + + } + + public static List from(List timetableLectures) { + List InnerTimetableLectureResponses = new ArrayList<>(); + + for (TimetableLecture timetableLecture : timetableLectures) { + Lecture lecture = timetableLecture.getLecture(); + InnerTimetableLectureResponseV3 responseV3; + + if (lecture == null) { + responseV3 = new InnerTimetableLectureResponseV3( + timetableLecture.getId(), + null, + null, + null, + null, + null, + timetableLecture.getMemo(), + timetableLecture.getGrades(), + timetableLecture.getClassTitle(), + null, + null, + timetableLecture.getProfessor(), + null + ); + } else { + responseV3 = new InnerTimetableLectureResponseV3( + timetableLecture.getId(), + lecture.getId(), + lecture.getRegularNumber(), + lecture.getCode(), + lecture.getDesignScore(), + null, + timetableLecture.getMemo(), + lecture.getGrades(), + timetableLecture.getClassTitle() == null ? lecture.getName() : timetableLecture.getClassTitle(), + lecture.getLectureClass(), + lecture.getTarget(), + lecture.getProfessor(), + lecture.getDepartment() + ); + } + InnerTimetableLectureResponses.add(responseV3); + } + return InnerTimetableLectureResponses; + } + } + + public static TimetableLectureResponseV3 of(TimetableFrame frame, int grades, int totalGrades) { + return new TimetableLectureResponseV3( + frame.getId(), + InnerTimetableLectureResponseV3.from(frame.getTimetableLectures()), + grades, + totalGrades + ); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java new file mode 100644 index 0000000000..8bb5a07311 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java @@ -0,0 +1,18 @@ +package in.koreatech.koin.domain.timetableV3.repository; + +import java.util.Optional; + +import org.springframework.data.repository.Repository; + +import in.koreatech.koin.domain.timetable.exception.LectureNotFoundException; +import in.koreatech.koin.domain.timetable.model.Lecture; + +public interface LectureRepositoryV3 extends Repository { + + Optional findById(Integer id); + + default Lecture getById(Integer id) { + return findById(id) + .orElseThrow(() -> LectureNotFoundException.withDetail("lecture_id: " + id)); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableFrameRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableFrameRepositoryV3.java new file mode 100644 index 0000000000..65350b97d9 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableFrameRepositoryV3.java @@ -0,0 +1,21 @@ +package in.koreatech.koin.domain.timetableV3.repository; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.repository.Repository; + +import in.koreatech.koin.domain.timetable.exception.TimetableNotFoundException; +import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; + +public interface TimetableFrameRepositoryV3 extends Repository { + + Optional findById(Integer id); + + default TimetableFrame getById(Integer id) { + return findById(id) + .orElseThrow(() -> TimetableNotFoundException.withDetail("id: " + id)); + } + + List findByUserIdAndIsMainTrue(Integer userId); +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java new file mode 100644 index 0000000000..c370c5b7e0 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java @@ -0,0 +1,9 @@ +package in.koreatech.koin.domain.timetableV3.repository; + +import org.springframework.data.repository.Repository; + +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; + +public interface TimetableLectureRepositoryV3 extends Repository { + TimetableLecture save(TimetableLecture timetableLecture); +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java new file mode 100644 index 0000000000..3f780bbba4 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java @@ -0,0 +1,47 @@ +package in.koreatech.koin.domain.timetableV3.service; + +import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; +import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; +import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import in.koreatech.koin.domain.timetable.model.Lecture; +import in.koreatech.koin.domain.timetableV2.dto.response.TimetableLectureResponse; +import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; +import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; +import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class TimetableLectureServiceV3 { + + private final TimetableLectureRepositoryV3 timetableLectureRepositoryV3; + private final TimetableFrameRepositoryV3 timetableFrameRepositoryV3; + private final LectureRepositoryV3 lectureRepositoryV3; + + @Transactional + public TimetableLectureResponseV3 createTimetablesRegularLecture( + TimetableRegularLectureCreateRequest request, Integer userId + ) { + TimetableFrame frame = timetableFrameRepositoryV3.getById(userId); + validateUserAuthorization(frame.getUser().getId(), userId); + Lecture lecture = lectureRepositoryV3.getById(request.lectureId()); + TimetableLecture timetableLecture = request.toTimetableLecture(frame, lecture); + timetableLectureRepositoryV3.save(timetableLecture); + return getTimetableLectureResponse(userId, frame); + } + + private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, TimetableFrame timetableFrame) { + int grades = calculateGradesMainFrame(timetableFrame); + int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); + return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); + } +} From ad0331f928b1b1383d0d95c177d53d24d0352632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 21 Dec 2024 21:39:19 +0900 Subject: [PATCH 02/61] =?UTF-8?q?chore:=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...tableLectureApiV3.java => TimetableRegularLectureApiV3.java} | 2 +- ...ntrollerV3.java => TimetableRegularLectureControllerV3.java} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/main/java/in/koreatech/koin/domain/timetableV3/controller/{TimetableLectureApiV3.java => TimetableRegularLectureApiV3.java} (97%) rename src/main/java/in/koreatech/koin/domain/timetableV3/controller/{TimetableLectureControllerV3.java => TimetableRegularLectureControllerV3.java} (96%) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java similarity index 97% rename from src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java rename to src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java index eb98d856a7..8a3eaee760 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java @@ -19,7 +19,7 @@ import jakarta.validation.Valid; @Tag(name = "(Normal) Timetable: V3-시간표", description = "시간표 강의 정보를 관리한다") -public interface TimetableLectureApiV3 { +public interface TimetableRegularLectureApiV3 { @ApiResponses( value = { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java similarity index 96% rename from src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java rename to src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java index 354b8a4994..2f2daf0844 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java @@ -16,7 +16,7 @@ @RestController @RequiredArgsConstructor -public class TimetableLectureControllerV3 { +public class TimetableRegularLectureControllerV3 { private final TimetableLectureServiceV3 timetableLectureV3; From 0585662316484a860e394dda77a274a059f7abb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 21 Dec 2024 21:40:09 +0900 Subject: [PATCH 03/61] =?UTF-8?q?chore:=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EC=84=A4=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 --- .../timetableV3/controller/TimetableRegularLectureApiV3.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java index 8a3eaee760..7894f50639 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java @@ -18,7 +18,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -@Tag(name = "(Normal) Timetable: V3-시간표", description = "시간표 강의 정보를 관리한다") +@Tag(name = "(Normal) Timetable: V3-시간표", description = "시간표 정규 강의 정보를 관리한다") public interface TimetableRegularLectureApiV3 { @ApiResponses( From 41f3a25fb1a864f9695f067acc235d0b52b5bbaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 21 Dec 2024 21:41:30 +0900 Subject: [PATCH 04/61] =?UTF-8?q?chore:=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV3/controller/TimetableRegularLectureApiV3.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java index 7894f50639..526532cd7a 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java @@ -24,6 +24,7 @@ public interface TimetableRegularLectureApiV3 { @ApiResponses( value = { @ApiResponse(responseCode = "201"), + @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) From f004f2042cec2ecfd8a4306329f30c26d3c1a9ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 21 Dec 2024 21:52:47 +0900 Subject: [PATCH 05/61] =?UTF-8?q?chore:=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TimetableRegularLectureControllerV3.java | 4 ++-- ...ureServiceV3.java => TimetableCustomLectureServiceV3.java} | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) rename src/main/java/in/koreatech/koin/domain/timetableV3/service/{TimetableLectureServiceV3.java => TimetableCustomLectureServiceV3.java} (95%) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java index 2f2daf0844..c4d5ac4219 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java @@ -9,7 +9,7 @@ import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; -import in.koreatech.koin.domain.timetableV3.service.TimetableLectureServiceV3; +import in.koreatech.koin.domain.timetableV3.service.TimetableCustomLectureServiceV3; import in.koreatech.koin.global.auth.Auth; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -18,7 +18,7 @@ @RequiredArgsConstructor public class TimetableRegularLectureControllerV3 { - private final TimetableLectureServiceV3 timetableLectureV3; + private final TimetableCustomLectureServiceV3 timetableLectureV3; @PostMapping("/v3/timetables/lecture/regular") ResponseEntity createTimetablesRegularLecture( diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java similarity index 95% rename from src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java rename to src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index 3f780bbba4..5a0cbb099a 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -8,7 +8,6 @@ import org.springframework.transaction.annotation.Transactional; import in.koreatech.koin.domain.timetable.model.Lecture; -import in.koreatech.koin.domain.timetableV2.dto.response.TimetableLectureResponse; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; @@ -21,7 +20,7 @@ @Service @RequiredArgsConstructor @Transactional(readOnly = true) -public class TimetableLectureServiceV3 { +public class TimetableCustomLectureServiceV3 { private final TimetableLectureRepositoryV3 timetableLectureRepositoryV3; private final TimetableFrameRepositoryV3 timetableFrameRepositoryV3; From 02645454178ae58e88695e5b3ad2264ba1ac1518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 21 Dec 2024 21:53:22 +0900 Subject: [PATCH 06/61] =?UTF-8?q?chore:=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TimetableRegularLectureControllerV3.java | 4 ++-- ...reServiceV3.java => TimetableRegularLectureServiceV3.java} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/main/java/in/koreatech/koin/domain/timetableV3/service/{TimetableCustomLectureServiceV3.java => TimetableRegularLectureServiceV3.java} (98%) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java index c4d5ac4219..0cb4cabc81 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java @@ -9,7 +9,7 @@ import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; -import in.koreatech.koin.domain.timetableV3.service.TimetableCustomLectureServiceV3; +import in.koreatech.koin.domain.timetableV3.service.TimetableRegularLectureServiceV3; import in.koreatech.koin.global.auth.Auth; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -18,7 +18,7 @@ @RequiredArgsConstructor public class TimetableRegularLectureControllerV3 { - private final TimetableCustomLectureServiceV3 timetableLectureV3; + private final TimetableRegularLectureServiceV3 timetableLectureV3; @PostMapping("/v3/timetables/lecture/regular") ResponseEntity createTimetablesRegularLecture( diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java similarity index 98% rename from src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java rename to src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index 5a0cbb099a..c4ef4a8a9a 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -20,7 +20,7 @@ @Service @RequiredArgsConstructor @Transactional(readOnly = true) -public class TimetableCustomLectureServiceV3 { +public class TimetableRegularLectureServiceV3 { private final TimetableLectureRepositoryV3 timetableLectureRepositoryV3; private final TimetableFrameRepositoryV3 timetableFrameRepositoryV3; From a1c495936cd08b7f2db755e9da3c365b82b94f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 22 Dec 2024 00:00:16 +0900 Subject: [PATCH 07/61] =?UTF-8?q?feat:=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EA=B0=95=EC=9D=98=20=EC=83=9D=EC=84=B1=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV2/model/TimetableLecture.java | 16 ++++ .../TimetableCustomLectureApiV3.java | 41 +++++++++ .../TimetableCustomLectureControllerV3.java | 31 +++++++ .../TimetableCustomLectureCreateRequest.java | 88 +++++++++++++++++++ .../response/TimetableLectureResponseV3.java | 34 ++++++- .../TimetableCustomLectureInformation.java | 61 +++++++++++++ .../TimetableCustomLectureRepositoryV3.java | 8 ++ .../TimetableCustomLectureServiceV3.java | 50 +++++++++++ ...e_timetable_custom_lecture_information.sql | 9 ++ 9 files changed, 336 insertions(+), 2 deletions(-) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableCustomLectureInformation.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableCustomLectureRepositoryV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java create mode 100644 src/main/resources/db/migration/V108__create_timetable_custom_lecture_information.sql diff --git a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java index 3d260945f6..fa50b9a8ed 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java @@ -3,11 +3,16 @@ import static jakarta.persistence.GenerationType.IDENTITY; import static lombok.AccessLevel.PROTECTED; +import java.util.ArrayList; +import java.util.List; + import org.hibernate.annotations.Where; import in.koreatech.koin.domain.timetable.dto.TimetableUpdateRequest; import in.koreatech.koin.domain.timetable.model.Lecture; +import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; import in.koreatech.koin.global.domain.BaseEntity; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -16,6 +21,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.Lob; import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -71,6 +77,9 @@ public class TimetableLecture extends BaseEntity { @JoinColumn(name = "frame_id") private TimetableFrame timetableFrame; + @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) + private List timetableCustomLectureInformations = new ArrayList<>(); + @Builder public TimetableLecture(String classTitle, String classTime, String classPlace, String professor, String grades, String memo, boolean isDeleted, Lecture lecture, TimetableFrame timetableFrame) { @@ -114,4 +123,11 @@ public void delete() { public void undelete() { this.isDeleted = false; } + + public void addTimetableCustomLectureInformation( + TimetableCustomLectureInformation timetableCustomLectureInformation + ) { + timetableCustomLectureInformations.add(timetableCustomLectureInformation); + timetableCustomLectureInformation.setTimetableLectureId(this); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java new file mode 100644 index 0000000000..81212999d4 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java @@ -0,0 +1,41 @@ +package in.koreatech.koin.domain.timetableV3.controller; + +import static in.koreatech.koin.domain.user.model.UserType.STUDENT; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import in.koreatech.koin.global.auth.Auth; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; + +@Tag(name = "(Normal) Timetable: V3-시간표", description = "시간표 커스텀 강의 정보를 관리한다") +public interface TimetableCustomLectureApiV3 { + + @ApiResponses( + value = { + @ApiResponse(responseCode = "201"), + @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) + } + ) + @Operation(summary = "커스텀 강의 생성") + @SecurityRequirement(name = "Jwt Authentication") + @PostMapping("/v3/timetables/lecture/custom") + ResponseEntity createTimetablesCustomLecture( + @Valid @RequestBody TimetableCustomLectureCreateRequest request, + @Auth(permit = {STUDENT}) Integer userId + ); +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java new file mode 100644 index 0000000000..51393f0e03 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java @@ -0,0 +1,31 @@ +package in.koreatech.koin.domain.timetableV3.controller; + +import static in.koreatech.koin.domain.user.model.UserType.STUDENT; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import in.koreatech.koin.domain.timetableV3.service.TimetableCustomLectureServiceV3; +import in.koreatech.koin.global.auth.Auth; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class TimetableCustomLectureControllerV3 { + + private final TimetableCustomLectureServiceV3 customLectureServiceV3; + + @PostMapping("/v3/timetables/lecture/custom") + public ResponseEntity createTimetablesCustomLecture( + @Valid @RequestBody TimetableCustomLectureCreateRequest request, + @Auth(permit = {STUDENT}) Integer userId + ) { + TimetableLectureResponseV3 response = customLectureServiceV3.createTimetablesCustomLecture(request, userId); + return ResponseEntity.ok(response); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java new file mode 100644 index 0000000000..7e3e071bf4 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java @@ -0,0 +1,88 @@ +package in.koreatech.koin.domain.timetableV3.dto.request; + +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; + +import java.util.List; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +@JsonNaming(value = SnakeCaseStrategy.class) +public record TimetableCustomLectureCreateRequest( + @NotNull(message = "시간표 프레임 id를 입력해주세요.") + @Schema(description = "시간표 프레임 id", example = "1004", requiredMode = REQUIRED) + Integer timetableFrameId, + + @Valid + @Schema(description = "커스텀 강의 정보", requiredMode = REQUIRED) + @NotNull(message = "커스텀 강의 정보를 입력해주세요.") + InnerTimeTableCustomLectureRequest timetableLecture +) { + @JsonNaming(value = SnakeCaseStrategy.class) + public record InnerTimeTableCustomLectureRequest( + @Schema(description = "커스텀 강의 이름", example = "커스텀 강의 이름", requiredMode = NOT_REQUIRED) + @Size(max = 100, message = "커스텀 강의 이름의 최대 글자는 100글자 입니다.") + String classTitle, + + @Valid + @Schema(description = "커스텀 강의 시간 정보", requiredMode = REQUIRED) + List lectureInfos, + + @Schema(description = "교수명", example = "교수명", requiredMode = NOT_REQUIRED) + @Size(max = 30, message = "교수명의 최대 글자는 30글자 입니다.") + String professor, + + @Schema(description = "학점", example = "3", requiredMode = NOT_REQUIRED) + @Size(max = 2, message = "학점은 두 글자 이상일 수 없습니다. (0~9)") + String grades, + + @Schema(description = "메모", example = "메모", requiredMode = NOT_REQUIRED) + @Size(max = 200, message = "메모는 200자 이하로 입력해주세요.") + String memo + ) { + @JsonNaming(value = SnakeCaseStrategy.class) + public record LectureInfo( + @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) + Integer startTime, + + @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) + Integer endTime, + + @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) + String place + ) { + + } + } + + public TimetableLecture toTimetableLecture(TimetableFrame frame) { + return TimetableLecture.builder() + .classTitle(timetableLecture.classTitle) + .professor(timetableLecture.professor) + .grades(timetableLecture.grades) + .memo(timetableLecture.memo) + .timetableFrame(frame) + .build(); + } + + public List toTimetableCustomLectureInformations() { + return timetableLecture.lectureInfos.stream() + .map(lectureInfo -> TimetableCustomLectureInformation.builder() + .startTime(lectureInfo.startTime) + .endTime(lectureInfo.endTime) + .place(lectureInfo.place) + .build() + ) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java index ca99e89f23..d1f278fa65 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java @@ -6,12 +6,15 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import com.fasterxml.jackson.databind.annotation.JsonNaming; import in.koreatech.koin.domain.timetable.model.Lecture; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; @JsonNaming(value = SnakeCaseStrategy.class) @@ -83,7 +86,34 @@ public record LectureInfo( @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) String place ) { + private static final Integer DIVIDE_TIME_UNIT = 100; + + public static List getCustomLectureInfo( + List timetableCustomLectureInformations + ) { + return timetableCustomLectureInformations.stream() + .map(timetableCustomLectureInformation -> new LectureInfo( + calcWeek(timetableCustomLectureInformation.getStartTime()), + timetableCustomLectureInformation.getStartTime(), + timetableCustomLectureInformation.getEndTime(), + getResponsePlace(timetableCustomLectureInformation.getPlace()) + )) + .collect(Collectors.toList()); + } + + private static Integer calcWeek(Integer startTime) { + if (startTime != 0) { + return startTime % DIVIDE_TIME_UNIT; + } + return 0; + } + private static String getResponsePlace(String place) { + if (Objects.isNull(place)) { + return ""; + } + return place; + } } public static List from(List timetableLectures) { @@ -100,7 +130,7 @@ public static List from(List null, null, null, - null, + LectureInfo.getCustomLectureInfo(timetableLecture.getTimetableCustomLectureInformations()), timetableLecture.getMemo(), timetableLecture.getGrades(), timetableLecture.getClassTitle(), @@ -108,7 +138,7 @@ public static List from(List null, timetableLecture.getProfessor(), null - ); + ); } else { responseV3 = new InnerTimetableLectureResponseV3( timetableLecture.getId(), diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableCustomLectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableCustomLectureInformation.java new file mode 100644 index 0000000000..07e356d282 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableCustomLectureInformation.java @@ -0,0 +1,61 @@ +package in.koreatech.koin.domain.timetableV3.model; + +import static jakarta.persistence.GenerationType.IDENTITY; +import static lombok.AccessLevel.PROTECTED; + +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Table(name = "timetable_custom_lecture_information") +@NoArgsConstructor(access = PROTECTED) +public class TimetableCustomLectureInformation { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Integer id; + + @NotNull + @Column(name = "start_time", nullable = false) + private Integer startTime; + + @NotNull + @Column(name = "end_time", nullable = false) + private Integer endTime; + + @Column(name = "place") + private String place; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "timetable_lecture_id") + private TimetableLecture timetableLecture; + + @Builder + public TimetableCustomLectureInformation( + Integer startTime, + Integer endTime, + String place, + TimetableLecture timetableLecture + ) { + this.startTime = startTime; + this.endTime = endTime; + this.place = place; + this.timetableLecture = timetableLecture; + } + + public void setTimetableLectureId(TimetableLecture timetableLecture) { + this.timetableLecture = timetableLecture; + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableCustomLectureRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableCustomLectureRepositoryV3.java new file mode 100644 index 0000000000..930d903c5a --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableCustomLectureRepositoryV3.java @@ -0,0 +1,8 @@ +package in.koreatech.koin.domain.timetableV3.repository; + +import org.springframework.data.repository.Repository; + +import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; + +public interface TimetableCustomLectureRepositoryV3 extends Repository { +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java new file mode 100644 index 0000000000..7f36c8da2c --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -0,0 +1,50 @@ +package in.koreatech.koin.domain.timetableV3.service; + +import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; +import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; +import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; + +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; +import in.koreatech.koin.domain.timetableV3.repository.TimetableCustomLectureRepositoryV3; +import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; +import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class TimetableCustomLectureServiceV3 { + + private final TimetableFrameRepositoryV3 timetableFrameRepositoryV3; + private final TimetableLectureRepositoryV3 timetableLectureRepositoryV3; + + @Transactional + public TimetableLectureResponseV3 createTimetablesCustomLecture( + TimetableCustomLectureCreateRequest request, Integer userId + ) { + TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); + validateUserAuthorization(frame.getUser().getId(), userId); + TimetableLecture timetableLecture = request.toTimetableLecture(frame); + List timetableCustomLectureInformations = request.toTimetableCustomLectureInformations(); + for (TimetableCustomLectureInformation timetableCustomLectureInformation : timetableCustomLectureInformations) { + timetableLecture.addTimetableCustomLectureInformation(timetableCustomLectureInformation); + } + timetableLectureRepositoryV3.save(timetableLecture); + return getTimetableLectureResponse(userId, frame); + } + + private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, TimetableFrame timetableFrame) { + int grades = calculateGradesMainFrame(timetableFrame); + int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); + return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); + } +} diff --git a/src/main/resources/db/migration/V108__create_timetable_custom_lecture_information.sql b/src/main/resources/db/migration/V108__create_timetable_custom_lecture_information.sql new file mode 100644 index 0000000000..efefff9c9d --- /dev/null +++ b/src/main/resources/db/migration/V108__create_timetable_custom_lecture_information.sql @@ -0,0 +1,9 @@ +CREATE TABLE `koin`.`timetable_custom_lecture_information` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '고유 id', + `timetable_lecture_id` INT UNSIGNED NOT NULL COMMENT 'timetableLecture id', + `start_time` INT UNSIGNED NOT NULL COMMENT '시작 시간', + `end_time` INT UNSIGNED NOT NULL COMMENT '종료 시간', + `place` VARCHAR(255) NULL COMMENT '장소', + PRIMARY KEY (id), + INDEX(timetable_lecture_id) +) From a0b4c6c69f283729f8341996f1b35910d5427820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 22 Dec 2024 00:03:01 +0900 Subject: [PATCH 08/61] =?UTF-8?q?chore:=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20im?= =?UTF-8?q?port=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV3/controller/TimetableCustomLectureApiV3.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java index 81212999d4..91cd2c858a 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java @@ -7,7 +7,6 @@ import org.springframework.web.bind.annotation.RequestBody; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureCreateRequest; -import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.global.auth.Auth; import io.swagger.v3.oas.annotations.Operation; From 8149e60ea87498b84f519aeeb00bdc49ec27dee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 22 Dec 2024 00:33:45 +0900 Subject: [PATCH 09/61] =?UTF-8?q?fix:=20=EC=A1=B0=ED=9A=8C=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV3/service/TimetableRegularLectureServiceV3.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index c4ef4a8a9a..e5893575fc 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -30,7 +30,7 @@ public class TimetableRegularLectureServiceV3 { public TimetableLectureResponseV3 createTimetablesRegularLecture( TimetableRegularLectureCreateRequest request, Integer userId ) { - TimetableFrame frame = timetableFrameRepositoryV3.getById(userId); + TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); validateUserAuthorization(frame.getUser().getId(), userId); Lecture lecture = lectureRepositoryV3.getById(request.lectureId()); TimetableLecture timetableLecture = request.toTimetableLecture(frame, lecture); From 19f407fd73f29ea6680f909e53f6a7f50facb1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 22 Dec 2024 09:23:48 +0900 Subject: [PATCH 10/61] chore: api implements --- .../controller/TimetableCustomLectureControllerV3.java | 2 +- .../controller/TimetableRegularLectureControllerV3.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java index 51393f0e03..1fc123db7b 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java @@ -16,7 +16,7 @@ @RestController @RequiredArgsConstructor -public class TimetableCustomLectureControllerV3 { +public class TimetableCustomLectureControllerV3 implements TimetableCustomLectureApiV3 { private final TimetableCustomLectureServiceV3 customLectureServiceV3; diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java index 0cb4cabc81..1672c07e47 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java @@ -16,12 +16,12 @@ @RestController @RequiredArgsConstructor -public class TimetableRegularLectureControllerV3 { +public class TimetableRegularLectureControllerV3 implements TimetableRegularLectureApiV3 { private final TimetableRegularLectureServiceV3 timetableLectureV3; @PostMapping("/v3/timetables/lecture/regular") - ResponseEntity createTimetablesRegularLecture( + public ResponseEntity createTimetablesRegularLecture( @Valid @RequestBody TimetableRegularLectureCreateRequest request, @Auth(permit = {STUDENT}) Integer userId ) { From a9c29b6fa8e79eeb4119947e110a6cc69e489ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 22 Dec 2024 09:50:25 +0900 Subject: [PATCH 11/61] =?UTF-8?q?docs:=20TODO=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/TimetableCustomLectureCreateRequest.java | 1 + .../timetableV3/service/TimetableRegularLectureServiceV3.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java index 7e3e071bf4..c698df49a5 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java @@ -59,6 +59,7 @@ public record LectureInfo( Integer endTime, @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) + @Size(max = 30, message = "강의 장소의 최대 글자는 30글자입니다.") String place ) { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index e5893575fc..f44d89a0e5 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -34,6 +34,7 @@ public TimetableLectureResponseV3 createTimetablesRegularLecture( validateUserAuthorization(frame.getUser().getId(), userId); Lecture lecture = lectureRepositoryV3.getById(request.lectureId()); TimetableLecture timetableLecture = request.toTimetableLecture(frame, lecture); + // TODO. Lecture 정규화 되면 강의 시간, 장소 로직 넣어야함 timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); } From 598668a7317912bd70c3d55fd237350566ae589e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 22 Dec 2024 12:02:54 +0900 Subject: [PATCH 12/61] =?UTF-8?q?feat:=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EA=B0=95=EC=9D=98=20=EC=88=98=EC=A0=95=20API=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=ED=8B=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimetableCustomLectureApiV3.java | 20 ++++++ .../TimetableCustomLectureControllerV3.java | 11 +++ .../TimetableCustomLectureUpdateRequest.java | 68 +++++++++++++++++++ .../TimetableCustomLectureServiceV3.java | 9 +++ 4 files changed, 108 insertions(+) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java index 91cd2c858a..05682155b7 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java @@ -3,10 +3,13 @@ import static in.koreatech.koin.domain.user.model.UserType.STUDENT; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.global.auth.Auth; import io.swagger.v3.oas.annotations.Operation; @@ -37,4 +40,21 @@ ResponseEntity createTimetablesCustomLecture( @Valid @RequestBody TimetableCustomLectureCreateRequest request, @Auth(permit = {STUDENT}) Integer userId ); + + @ApiResponses( + value = { + @ApiResponse(responseCode = "201"), + @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) + } + ) + @Operation(summary = "커스텀 강의 수정") + @SecurityRequirement(name = "Jwt Authentication") + @PutMapping("/v3/timetables/lecture/custom") + ResponseEntity updateTimetablesCustomLecture( + @Valid @RequestBody TimetableCustomLectureUpdateRequest request, + @Auth(permit = {STUDENT}) Integer userId + ); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java index 1fc123db7b..7fbfabe4c1 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureControllerV3.java @@ -4,10 +4,12 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.service.TimetableCustomLectureServiceV3; import in.koreatech.koin.global.auth.Auth; @@ -28,4 +30,13 @@ public ResponseEntity createTimetablesCustomLecture( TimetableLectureResponseV3 response = customLectureServiceV3.createTimetablesCustomLecture(request, userId); return ResponseEntity.ok(response); } + + @PutMapping("/v3/timetables/lecture/custom") + public ResponseEntity updateTimetablesCustomLecture( + @Valid @RequestBody TimetableCustomLectureUpdateRequest request, + @Auth(permit = {STUDENT}) Integer userId + ) { + TimetableLectureResponseV3 response = customLectureServiceV3.updateTimetablesCustomLecture(request, userId); + return ResponseEntity.ok(response); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java new file mode 100644 index 0000000000..6938106cd1 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java @@ -0,0 +1,68 @@ +package in.koreatech.koin.domain.timetableV3.dto.request; + +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; + +import java.util.List; + +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +@JsonNaming(value = SnakeCaseStrategy.class) +public record TimetableCustomLectureUpdateRequest( + @NotNull(message = "시간표 프레임 id를 입력해주세요.") + @Schema(description = "시간표 프레임 id", example = "1004", requiredMode = REQUIRED) + Integer timetableFrameId, + + @Valid + @Schema(description = "커스텀 강의 정보", requiredMode = REQUIRED) + @NotNull(message = "커스텀 강의 정보를 입력해주세요.") + InnerTimeTableCustomLectureRequest timetableLecture +) { + @JsonNaming(value = SnakeCaseStrategy.class) + public record InnerTimeTableCustomLectureRequest( + @Schema(description = "시간표 id", example = "1", requiredMode = REQUIRED) + @NotNull(message = "시간표 id를 입력해주세요.") + Integer id, + + @Schema(description = "커스텀 강의 이름", example = "커스텀 강의 이름", requiredMode = NOT_REQUIRED) + @Size(max = 100, message = "커스텀 강의 이름의 최대 글자는 100글자 입니다.") + String classTitle, + + @Valid + @Schema(description = "커스텀 강의 시간 정보", requiredMode = REQUIRED) + List lectureInfos, + + @Schema(description = "교수명", example = "교수명", requiredMode = NOT_REQUIRED) + @Size(max = 30, message = "교수명의 최대 글자는 30글자 입니다.") + String professor, + + @Schema(description = "학점", example = "3", requiredMode = NOT_REQUIRED) + @Size(max = 2, message = "학점은 두 글자 이상일 수 없습니다. (0~9)") + String grades, + + @Schema(description = "메모", example = "메모", requiredMode = NOT_REQUIRED) + @Size(max = 200, message = "메모는 200자 이하로 입력해주세요.") + String memo + ) { + @JsonNaming(value = SnakeCaseStrategy.class) + public record LectureInfo( + @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) + Integer startTime, + + @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) + Integer endTime, + + @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) + @Size(max = 30, message = "강의 장소의 최대 글자는 30글자입니다.") + String place + ) { + + } + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index 7f36c8da2c..54d1fecca9 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -11,7 +11,9 @@ import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import in.koreatech.koin.domain.timetableV3.controller.TimetableCustomLectureApiV3; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; import in.koreatech.koin.domain.timetableV3.repository.TimetableCustomLectureRepositoryV3; @@ -47,4 +49,11 @@ private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, T int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); } + + @Transactional + public TimetableLectureResponseV3 updateTimetablesCustomLecture( + TimetableCustomLectureUpdateRequest request, Integer userId + ) { + return null; + } } From 8c593effda04be383f78826ba95a956ef4397fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 22 Dec 2024 12:45:24 +0900 Subject: [PATCH 13/61] =?UTF-8?q?feat:=20=EC=A0=95=EA=B7=9C=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=20=EC=88=98=EC=A0=95=20API=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=ED=8B=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimetableRegularLectureApiV3.java | 18 +++++++ .../TimetableRegularLectureControllerV3.java | 11 ++++ .../TimetableRegularLectureUpdateRequest.java | 53 +++++++++++++++++++ .../TimetableRegularLectureServiceV3.java | 8 +++ 4 files changed, 90 insertions(+) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java index 526532cd7a..02c4d09511 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java @@ -4,9 +4,11 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.global.auth.Auth; import io.swagger.v3.oas.annotations.Operation; @@ -38,4 +40,20 @@ ResponseEntity createTimetablesRegularLecture( @Auth(permit = {STUDENT}) Integer userId ); + @ApiResponses( + value = { + @ApiResponse(responseCode = "201"), + @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) + } + ) + @Operation(summary = "정규 강의 수정") + @SecurityRequirement(name = "Jwt Authentication") + @PutMapping("/v3/timetables/lecture/regular") + ResponseEntity updateTimetablesRegularLecture( + @Valid @RequestBody TimetableRegularLectureUpdateRequest request, + @Auth(permit = {STUDENT}) Integer userId + ); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java index 1672c07e47..f6037ac092 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java @@ -4,10 +4,12 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.service.TimetableRegularLectureServiceV3; import in.koreatech.koin.global.auth.Auth; @@ -28,4 +30,13 @@ public ResponseEntity createTimetablesRegularLecture TimetableLectureResponseV3 response = timetableLectureV3.createTimetablesRegularLecture(request, userId); return ResponseEntity.ok(response); } + + @PutMapping("/v3/timetables/lecture/regular") + public ResponseEntity updateTimetablesRegularLecture( + @Valid @RequestBody TimetableRegularLectureUpdateRequest request, + @Auth(permit = {STUDENT}) Integer userId + ) { + TimetableLectureResponseV3 response = timetableLectureV3.updateTimetablesRegularLecture(request, userId); + return ResponseEntity.ok(response); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java new file mode 100644 index 0000000000..77e18c8073 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java @@ -0,0 +1,53 @@ +package in.koreatech.koin.domain.timetableV3.dto.request; + +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; + +import java.util.List; + +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +public record TimetableRegularLectureUpdateRequest( + @NotNull(message = "시간표 프레임 id를 입력해주세요.") + @Schema(description = "시간표 프레임 id", example = "1004", requiredMode = REQUIRED) + Integer timetableFrameId, + + @Valid + @Schema(description = "정규 강의 정보", requiredMode = REQUIRED) + @NotNull(message = "정규 강의 정보를 입력해주세요.") + InnerTimeTableRegularLectureRequest timetableLecture +) { + @JsonNaming(value = SnakeCaseStrategy.class) + public record InnerTimeTableRegularLectureRequest( + @Schema(description = "시간표 id", example = "1", requiredMode = REQUIRED) + @NotNull(message = "시간표 id를 입력해주세요.") + Integer id, + + @Schema(description = "강의 id", example = "3015", requiredMode = REQUIRED) + @NotNull(message = "강의 id를 입력해주세요.") + Integer lectureId, + + @Schema(description = "정규 강의 이름", example = "정규 강의 이름", requiredMode = NOT_REQUIRED) + @Size(max = 100, message = "정규 강의 이름의 최대 글자는 100글자 입니다.") + String classTitle, + + @Valid + @Schema(description = "정규 강의 장소 정보", requiredMode = REQUIRED) + List classPlaces + ) { + @JsonNaming(value = SnakeCaseStrategy.class) + public record ClassPlace( + @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) + @Size(max = 30, message = "강의 장소의 최대 글자는 30글자입니다.") + String classPlace + ) { + + } + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index f44d89a0e5..574cafff36 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -11,6 +11,7 @@ import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; +import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; @@ -44,4 +45,11 @@ private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, T int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); } + + @Transactional + public TimetableLectureResponseV3 updateTimetablesRegularLecture( + TimetableRegularLectureUpdateRequest request, Integer userId + ) { + return null; + } } From 76d6fc6b6f541dcfa7af1d2a841751abdbdec192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 22 Dec 2024 12:46:31 +0900 Subject: [PATCH 14/61] =?UTF-8?q?feat:=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EA=B0=95=EC=9D=98=20=EC=88=98=EC=A0=95=20API=20dto=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/TimetableCustomLectureUpdateRequest.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java index 6938106cd1..db6de32ca0 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java @@ -40,15 +40,7 @@ public record InnerTimeTableCustomLectureRequest( @Schema(description = "교수명", example = "교수명", requiredMode = NOT_REQUIRED) @Size(max = 30, message = "교수명의 최대 글자는 30글자 입니다.") - String professor, - - @Schema(description = "학점", example = "3", requiredMode = NOT_REQUIRED) - @Size(max = 2, message = "학점은 두 글자 이상일 수 없습니다. (0~9)") - String grades, - - @Schema(description = "메모", example = "메모", requiredMode = NOT_REQUIRED) - @Size(max = 200, message = "메모는 200자 이하로 입력해주세요.") - String memo + String professor ) { @JsonNaming(value = SnakeCaseStrategy.class) public record LectureInfo( From 17fe0be95f06d7c7b9e222b328c48f778d14f0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 22 Dec 2024 13:18:42 +0900 Subject: [PATCH 15/61] =?UTF-8?q?feat:=20timetableLectureV3=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EA=B8=B0=EB=B3=B8=20=ED=8B=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TimetableLectureApiV3.java | 38 +++++++++++++++++++ .../TimetableLectureControllerV3.java | 29 ++++++++++++++ .../TimetableRegularLectureUpdateRequest.java | 1 + .../service/TimetableLectureServiceV3.java | 15 ++++++++ 4 files changed, 83 insertions(+) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java new file mode 100644 index 0000000000..c8b6348ece --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java @@ -0,0 +1,38 @@ +package in.koreatech.koin.domain.timetableV3.controller; + +import static in.koreatech.koin.domain.user.model.UserType.STUDENT; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import in.koreatech.koin.domain.timetableV2.dto.response.TimetableLectureResponse; +import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import in.koreatech.koin.global.auth.Auth; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "(Normal) Timetable: V3-시간표", description = "시간표를 관리한다") +public interface TimetableLectureApiV3 { + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) + } + ) + @Operation(summary = "시간표 강의 정보 조회") + @SecurityRequirement(name = "Jwt Authentication") + @GetMapping("/v3/timetables/lecture") + ResponseEntity getTimetableLecture( + @RequestParam(value = "timetable_frame_id") Integer timetableFrameId, + @Auth(permit = {STUDENT}) Integer userId + ); +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java new file mode 100644 index 0000000000..83d0a0ec6c --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java @@ -0,0 +1,29 @@ +package in.koreatech.koin.domain.timetableV3.controller; + +import static in.koreatech.koin.domain.user.model.UserType.STUDENT; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import in.koreatech.koin.domain.timetableV3.service.TimetableLectureServiceV3; +import in.koreatech.koin.global.auth.Auth; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class TimetableLectureControllerV3 implements TimetableLectureApiV3 { + + private final TimetableLectureServiceV3 lectureServiceV3; + + @GetMapping("/v3/timetables/lecture") + public ResponseEntity getTimetableLecture( + @RequestParam(value = "timetable_frame_id") Integer timetableFrameId, + @Auth(permit = {STUDENT}) Integer userId + ) { + TimetableLectureResponseV3 response = lectureServiceV3.getTimetableLecture(timetableFrameId, userId); + return ResponseEntity.ok(response); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java index 77e18c8073..9a5e1dbb04 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java @@ -13,6 +13,7 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; +@JsonNaming(value = SnakeCaseStrategy.class) public record TimetableRegularLectureUpdateRequest( @NotNull(message = "시간표 프레임 id를 입력해주세요.") @Schema(description = "시간표 프레임 id", example = "1004", requiredMode = REQUIRED) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java new file mode 100644 index 0000000000..ea993a3863 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java @@ -0,0 +1,15 @@ +package in.koreatech.koin.domain.timetableV3.service; + +import org.springframework.stereotype.Service; + +import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class TimetableLectureServiceV3 { + + public TimetableLectureResponseV3 getTimetableLecture(Integer timetableFrameId, Integer userId) { + return null; + } +} From d440a4b81102afe0b4e57b7935b1e1d6f254009c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 22 Dec 2024 13:24:24 +0900 Subject: [PATCH 16/61] =?UTF-8?q?chore:=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20im?= =?UTF-8?q?port=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/timetableV3/controller/TimetableLectureApiV3.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java index c8b6348ece..54b498885f 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java @@ -6,7 +6,6 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; -import in.koreatech.koin.domain.timetableV2.dto.response.TimetableLectureResponse; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.global.auth.Auth; import io.swagger.v3.oas.annotations.Operation; From d3fa81a726b0168a645643beed9a0a0559ecfd9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 28 Dec 2024 12:36:21 +0900 Subject: [PATCH 17/61] =?UTF-8?q?chore:=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20im?= =?UTF-8?q?port=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV3/controller/TimetableCustomLectureApiV3.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java index 05682155b7..0904c2b849 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java @@ -3,7 +3,6 @@ import static in.koreatech.koin.domain.user.model.UserType.STUDENT; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; From 871b4b179bf8f7dfc61ee0b167007a1b44067682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 28 Dec 2024 13:31:59 +0900 Subject: [PATCH 18/61] feat: Lecture V3 --- .../timetableV3/controller/LectureApiV3.java | 32 +++++ .../controller/LectureControllerV3.java | 27 ++++ .../dto/response/LectureResponseV3.java | 118 ++++++++++++++++++ .../repository/LectureRepositoryV3.java | 3 + .../timetableV3/service/LectureServiceV3.java | 22 ++++ 5 files changed, 202 insertions(+) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java new file mode 100644 index 0000000000..ca67934343 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java @@ -0,0 +1,32 @@ +package in.koreatech.koin.domain.timetableV3.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; + +import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; + +@Tag(name = "(Normal) Lecture: V3-정규 강의", description = "정규 강의 정보를 관리한다") +public interface LectureApiV3 { + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))), + } + ) + @Operation(summary = "정규 강의 목록 조회") + @GetMapping("/lectures") + ResponseEntity> getLectures( + String semesterDate + ); +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java new file mode 100644 index 0000000000..b0739746e0 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java @@ -0,0 +1,27 @@ +package in.koreatech.koin.domain.timetableV3.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; +import in.koreatech.koin.domain.timetableV3.service.LectureServiceV3; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class LectureControllerV3 implements LectureApiV3 { + + private final LectureServiceV3 lectureServiceV3; + + // TODO. Semester v3 올라가면 파라미터 변경하기 + @GetMapping("/v3/lectures") + public ResponseEntity> getLectures( + String semesterDate + ) { + List response = lectureServiceV3.getLectures(semesterDate); + return ResponseEntity.ok(response); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java new file mode 100644 index 0000000000..0db3b9b678 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java @@ -0,0 +1,118 @@ +package in.koreatech.koin.domain.timetableV3.dto.response; + +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import in.koreatech.koin.domain.timetable.model.Lecture; +import io.swagger.v3.oas.annotations.media.Schema; + +@JsonNaming(value = SnakeCaseStrategy.class) +public record LectureResponseV3( + + @Schema(description = "과목 id", example = "1", requiredMode = REQUIRED) + Integer id, + + @Schema(description = "과목 코드", example = "ARB244", requiredMode = REQUIRED) + String code, + + @Schema(description = "과목 이름", example = "건축구조의 이해 및 실습", requiredMode = REQUIRED) + String name, + + @Schema(description = "대상 학년", example = "3", requiredMode = REQUIRED) + String grades, + + @Schema(description = "분반", example = "01", requiredMode = REQUIRED) + String lectureClass, + + @Schema(description = "수강 인원", example = "25", requiredMode = NOT_REQUIRED) + String regularNumber, + + @Schema(description = "학부", example = "디자인ㆍ건축공학부", requiredMode = REQUIRED) + String department, + + @Schema(description = "대상", example = "디자 1 건축", requiredMode = REQUIRED) + String target, + + @Schema(description = "강의 교수", example = "이돈우", requiredMode = NOT_REQUIRED) + String professor, + + @Schema(description = "영어 수업 여무", example = "N", requiredMode = REQUIRED) + String isEnglish, + + @Schema(description = "설계 학점", example = "0", requiredMode = REQUIRED) + String designScore, + + @Schema(description = "이러닝 여부", example = "Y", requiredMode = REQUIRED) + String isElearning, + + @Schema(description = "강의 정보", requiredMode = REQUIRED) + List lectureInfos +) { + @JsonNaming(value = SnakeCaseStrategy.class) + public record LectureInfo( + @Schema(description = "요일", example = "0", requiredMode = REQUIRED) + Integer week, + + @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) + Integer startTime, + + @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) + Integer endTime + ) { + public static List of(String classTime) { + List classTimes = convertList(classTime); + if (classTimes.isEmpty()) { + return List.of(); + } + + List response = new ArrayList<>(); + int size = classTimes.size(); + Integer startTime = classTimes.get(0); + Integer prevTime = classTimes.get(0); + + for (int index = 1; index < size; index++) { + if (prevTime + 1 != classTimes.get(index)) { + response.add(new LectureInfo(startTime / 100, startTime, prevTime)); + startTime = classTimes.get(index); + } + prevTime = classTimes.get(index); + } + response.add(new LectureInfo(startTime / 100, startTime, prevTime)); + + return response; + } + + public static List convertList(String classTime) { + return Stream.of(classTime.replaceAll("[\\[\\]]", "").split(",")) + .map(String::strip) + .filter(time -> !time.isEmpty()) + .map(Integer::parseInt) + .toList(); + } + } + + public static LectureResponseV3 of(Lecture lecture) { + return new LectureResponseV3( + lecture.getId(), + lecture.getCode(), + lecture.getName(), + lecture.getGrades(), + lecture.getLectureClass(), + lecture.getRegularNumber(), + lecture.getDepartment(), + lecture.getTarget(), + lecture.getProfessor(), + lecture.getIsEnglish(), + lecture.getDesignScore(), + lecture.getIsElearning(), + LectureInfo.of(lecture.getClassTime()) + ); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java index 8bb5a07311..47e0d3b620 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java @@ -1,5 +1,6 @@ package in.koreatech.koin.domain.timetableV3.repository; +import java.util.List; import java.util.Optional; import org.springframework.data.repository.Repository; @@ -15,4 +16,6 @@ default Lecture getById(Integer id) { return findById(id) .orElseThrow(() -> LectureNotFoundException.withDetail("lecture_id: " + id)); } + + List findBySemester(String semesterDate); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java new file mode 100644 index 0000000000..f6b7074b18 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java @@ -0,0 +1,22 @@ +package in.koreatech.koin.domain.timetableV3.service; + +import java.util.List; + +import org.springframework.stereotype.Service; + +import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; +import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class LectureServiceV3 { + + private final LectureRepositoryV3 lectureRepositoryV3; + + public List getLectures(String semesterDate) { + return lectureRepositoryV3.findBySemester(semesterDate).stream() + .map(LectureResponseV3::of) + .toList(); + } +} From 5548bce3012206dfb285b78b4443cbd3e6273fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 28 Dec 2024 14:10:12 +0900 Subject: [PATCH 19/61] =?UTF-8?q?feat:=20lecture=20=EC=A0=95=EA=B7=9C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/LectureResponseV3.java | 38 +++++------------ .../timetableV3/model/LectureInformation.java | 41 +++++++++++++++++++ .../LectureInformationRepositoryV3.java | 11 +++++ .../timetableV3/service/LectureServiceV3.java | 18 ++++++-- ...V109__create_lecture_information_table.sql | 8 ++++ 5 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureInformationRepositoryV3.java create mode 100644 src/main/resources/db/migration/V109__create_lecture_information_table.sql diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java index 0db3b9b678..e448f38ac6 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java @@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.annotation.JsonNaming; import in.koreatech.koin.domain.timetable.model.Lecture; +import in.koreatech.koin.domain.timetableV3.model.LectureInformation; import io.swagger.v3.oas.annotations.media.Schema; @JsonNaming(value = SnakeCaseStrategy.class) @@ -66,39 +67,22 @@ public record LectureInfo( @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) Integer endTime ) { - public static List of(String classTime) { - List classTimes = convertList(classTime); - if (classTimes.isEmpty()) { - return List.of(); - } - + public static List of(List lectureInformations) { List response = new ArrayList<>(); - int size = classTimes.size(); - Integer startTime = classTimes.get(0); - Integer prevTime = classTimes.get(0); - - for (int index = 1; index < size; index++) { - if (prevTime + 1 != classTimes.get(index)) { - response.add(new LectureInfo(startTime / 100, startTime, prevTime)); - startTime = classTimes.get(index); - } - prevTime = classTimes.get(index); + + for (LectureInformation lectureInformation : lectureInformations) { + response.add(new LectureInfo( + lectureInformation.getStarTime() / 100, + lectureInformation.getStarTime(), + lectureInformation.getEndTime()) + ); } - response.add(new LectureInfo(startTime / 100, startTime, prevTime)); return response; } - - public static List convertList(String classTime) { - return Stream.of(classTime.replaceAll("[\\[\\]]", "").split(",")) - .map(String::strip) - .filter(time -> !time.isEmpty()) - .map(Integer::parseInt) - .toList(); - } } - public static LectureResponseV3 of(Lecture lecture) { + public static LectureResponseV3 from(Lecture lecture, List lectureInformations) { return new LectureResponseV3( lecture.getId(), lecture.getCode(), @@ -112,7 +96,7 @@ public static LectureResponseV3 of(Lecture lecture) { lecture.getIsEnglish(), lecture.getDesignScore(), lecture.getIsElearning(), - LectureInfo.of(lecture.getClassTime()) + LectureInfo.of(lectureInformations) ); } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java new file mode 100644 index 0000000000..1d82cc63ce --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java @@ -0,0 +1,41 @@ +package in.koreatech.koin.domain.timetableV3.model; + +import static jakarta.persistence.GenerationType.IDENTITY; +import static lombok.AccessLevel.PROTECTED; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Table(name = "lecture_information") +@NoArgsConstructor(access = PROTECTED) +public class LectureInformation { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Integer id; + + @Column(name = "lecture_id") + private Integer lectureId; + + // TODO. 시작시간과 끝시간 유효성 체크 로직 추가 + @Column(name = "start_time") + private Integer starTime; + + @Column(name = "end_time") + private Integer endTime; + + @Builder + public LectureInformation(Integer lectureId, Integer starTime, Integer endTime) { + this.lectureId = lectureId; + this.starTime = starTime; + this.endTime = endTime; + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureInformationRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureInformationRepositoryV3.java new file mode 100644 index 0000000000..6b38020d3c --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureInformationRepositoryV3.java @@ -0,0 +1,11 @@ +package in.koreatech.koin.domain.timetableV3.repository; + +import java.util.List; + +import org.springframework.data.repository.Repository; + +import in.koreatech.koin.domain.timetableV3.model.LectureInformation; + +public interface LectureInformationRepositoryV3 extends Repository { + List findByLectureId(Integer lectureId); +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java index f6b7074b18..ee67d8be0f 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java @@ -1,10 +1,14 @@ package in.koreatech.koin.domain.timetableV3.service; +import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Service; +import in.koreatech.koin.domain.timetable.model.Lecture; import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; +import in.koreatech.koin.domain.timetableV3.model.LectureInformation; +import in.koreatech.koin.domain.timetableV3.repository.LectureInformationRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; import lombok.RequiredArgsConstructor; @@ -12,11 +16,19 @@ @RequiredArgsConstructor public class LectureServiceV3 { + private final LectureInformationRepositoryV3 lectureInformationRepositoryV3; private final LectureRepositoryV3 lectureRepositoryV3; public List getLectures(String semesterDate) { - return lectureRepositoryV3.findBySemester(semesterDate).stream() - .map(LectureResponseV3::of) - .toList(); + List lectures = lectureRepositoryV3.findBySemester(semesterDate); + List response = new ArrayList<>(); + + for (Lecture lecture : lectures) { + List lectureInformations = lectureInformationRepositoryV3.findByLectureId( + lecture.getId()); + response.add(LectureResponseV3.from(lecture, lectureInformations)); + } + + return response; } } diff --git a/src/main/resources/db/migration/V109__create_lecture_information_table.sql b/src/main/resources/db/migration/V109__create_lecture_information_table.sql new file mode 100644 index 0000000000..41acca0486 --- /dev/null +++ b/src/main/resources/db/migration/V109__create_lecture_information_table.sql @@ -0,0 +1,8 @@ +CREATE TABLE `koin`.`lecture_information`( + `id` int UNSIGNED NOT NULL AUTO_INCREMENT, + `lecture_id` int UNSIGNED NOT NULL, + `start_time` int NULL, + `end_time` int NULL, + PRIMARY KEY (`id`), + index (`lecture_id`) +); From 42aa76727dc8ee82089b129e79a9b13c2fabf9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 28 Dec 2024 14:32:07 +0900 Subject: [PATCH 20/61] =?UTF-8?q?chore:=20lecture=20-=20LectureInformation?= =?UTF-8?q?=20=EC=97=B0=EA=B0=84=EA=B4=80=EA=B3=84=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/timetable/model/Lecture.java | 10 ++++++++++ .../timetableV3/model/LectureInformation.java | 15 ++++++++++----- .../repository/LectureRepositoryV3.java | 10 ++++++++++ .../timetableV3/service/LectureServiceV3.java | 18 ++++-------------- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java b/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java index a786613af6..1ae5e57e93 100644 --- a/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java @@ -1,12 +1,19 @@ package in.koreatech.koin.domain.timetable.model; +import static jakarta.persistence.FetchType.LAZY; import static jakarta.persistence.GenerationType.IDENTITY; import static lombok.AccessLevel.PROTECTED; +import java.util.ArrayList; +import java.util.List; + +import in.koreatech.koin.domain.timetableV3.model.LectureInformation; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -86,6 +93,9 @@ public class Lecture { @Column(name = "class_time", nullable = false) private String classTime; + @OneToMany(cascade = CascadeType.ALL, mappedBy = "lecture", orphanRemoval = true) + private List lectureInformations = new ArrayList<>(); + @Builder public Lecture( String semester, diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java index 1d82cc63ce..1a7ee45bde 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java @@ -1,12 +1,16 @@ package in.koreatech.koin.domain.timetableV3.model; +import static jakarta.persistence.FetchType.LAZY; import static jakarta.persistence.GenerationType.IDENTITY; import static lombok.AccessLevel.PROTECTED; +import in.koreatech.koin.domain.timetable.model.Lecture; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import lombok.Builder; import lombok.Getter; @@ -22,9 +26,6 @@ public class LectureInformation { @GeneratedValue(strategy = IDENTITY) private Integer id; - @Column(name = "lecture_id") - private Integer lectureId; - // TODO. 시작시간과 끝시간 유효성 체크 로직 추가 @Column(name = "start_time") private Integer starTime; @@ -32,10 +33,14 @@ public class LectureInformation { @Column(name = "end_time") private Integer endTime; + @ManyToOne(fetch = LAZY) + @JoinColumn(name = "lecture_id") + private Lecture lecture; + @Builder - public LectureInformation(Integer lectureId, Integer starTime, Integer endTime) { - this.lectureId = lectureId; + public LectureInformation(Integer starTime, Integer endTime, Lecture lecture) { this.starTime = starTime; this.endTime = endTime; + this.lecture = lecture; } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java index 47e0d3b620..1db0031250 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java @@ -3,10 +3,12 @@ import java.util.List; import java.util.Optional; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; import in.koreatech.koin.domain.timetable.exception.LectureNotFoundException; import in.koreatech.koin.domain.timetable.model.Lecture; +import io.lettuce.core.dynamic.annotation.Param; public interface LectureRepositoryV3 extends Repository { @@ -18,4 +20,12 @@ default Lecture getById(Integer id) { } List findBySemester(String semesterDate); + + @Query(""" + SELECT l + FROM Lecture l + LEFT JOIN FETCH l.lectureInformations + WHERE l.semester = :semesterDate + """) + List findLecturesWithInformations(@Param("semesterDate") String semesterDate); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java index ee67d8be0f..6a32de63b4 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java @@ -1,14 +1,11 @@ package in.koreatech.koin.domain.timetableV3.service; -import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Service; import in.koreatech.koin.domain.timetable.model.Lecture; import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; -import in.koreatech.koin.domain.timetableV3.model.LectureInformation; -import in.koreatech.koin.domain.timetableV3.repository.LectureInformationRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; import lombok.RequiredArgsConstructor; @@ -16,19 +13,12 @@ @RequiredArgsConstructor public class LectureServiceV3 { - private final LectureInformationRepositoryV3 lectureInformationRepositoryV3; private final LectureRepositoryV3 lectureRepositoryV3; public List getLectures(String semesterDate) { - List lectures = lectureRepositoryV3.findBySemester(semesterDate); - List response = new ArrayList<>(); - - for (Lecture lecture : lectures) { - List lectureInformations = lectureInformationRepositoryV3.findByLectureId( - lecture.getId()); - response.add(LectureResponseV3.from(lecture, lectureInformations)); - } - - return response; + List lectures = lectureRepositoryV3.findLecturesWithInformations(semesterDate); + return lectures.stream() + .map(lecture -> LectureResponseV3.from(lecture, lecture.getLectureInformations())) + .toList(); } } From c387b98a8f4da42ee925a7e313a90b0353b71c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 29 Dec 2024 11:12:56 +0900 Subject: [PATCH 21/61] =?UTF-8?q?chore:=20=EB=A9=94=EC=86=8C=EB=93=9C=20?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EB=AF=B8=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=20import=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/timetableV3/dto/response/LectureResponseV3.java | 7 +++---- .../koin/domain/timetableV3/service/LectureServiceV3.java | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java index e448f38ac6..1519046a22 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Stream; import com.fasterxml.jackson.databind.annotation.JsonNaming; @@ -67,7 +66,7 @@ public record LectureInfo( @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) Integer endTime ) { - public static List of(List lectureInformations) { + public static List from(List lectureInformations) { List response = new ArrayList<>(); for (LectureInformation lectureInformation : lectureInformations) { @@ -82,7 +81,7 @@ public static List of(List lectureInformations) } } - public static LectureResponseV3 from(Lecture lecture, List lectureInformations) { + public static LectureResponseV3 of(Lecture lecture, List lectureInformations) { return new LectureResponseV3( lecture.getId(), lecture.getCode(), @@ -96,7 +95,7 @@ public static LectureResponseV3 from(Lecture lecture, List l lecture.getIsEnglish(), lecture.getDesignScore(), lecture.getIsElearning(), - LectureInfo.of(lectureInformations) + LectureInfo.from(lectureInformations) ); } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java index 6a32de63b4..88f4f5bbcc 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java @@ -18,7 +18,7 @@ public class LectureServiceV3 { public List getLectures(String semesterDate) { List lectures = lectureRepositoryV3.findLecturesWithInformations(semesterDate); return lectures.stream() - .map(lecture -> LectureResponseV3.from(lecture, lecture.getLectureInformations())) + .map(lecture -> LectureResponseV3.of(lecture, lecture.getLectureInformations())) .toList(); } } From 91b3fde9172e430e75ef7d8358729a4162fa2286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 29 Dec 2024 12:14:23 +0900 Subject: [PATCH 22/61] =?UTF-8?q?feat:=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EA=B0=95=EC=9D=98=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV2/model/TimetableLecture.java | 5 +++ .../response/TimetableLectureResponseV3.java | 2 +- .../TimetableLectureRepositoryV3.java | 10 +++++ .../TimetableCustomLectureServiceV3.java | 37 +++++++++++++++++-- 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java index fa50b9a8ed..0bf4e51821 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java @@ -130,4 +130,9 @@ public void addTimetableCustomLectureInformation( timetableCustomLectureInformations.add(timetableCustomLectureInformation); timetableCustomLectureInformation.setTimetableLectureId(this); } + + public void customLectureUpdate(String classTitle, String professor) { + this.classTitle = classTitle; + this.professor = professor; + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java index d1f278fa65..8c22ae4f1a 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java @@ -103,7 +103,7 @@ public static List getCustomLectureInfo( private static Integer calcWeek(Integer startTime) { if (startTime != 0) { - return startTime % DIVIDE_TIME_UNIT; + return startTime / DIVIDE_TIME_UNIT; } return 0; } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java index c370c5b7e0..7ec0b2892b 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java @@ -1,9 +1,19 @@ package in.koreatech.koin.domain.timetableV3.repository; +import java.util.Optional; + import org.springframework.data.repository.Repository; +import in.koreatech.koin.domain.timetableV2.exception.TimetableLectureNotFoundException; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; public interface TimetableLectureRepositoryV3 extends Repository { TimetableLecture save(TimetableLecture timetableLecture); + + Optional findById(Integer id); + + default TimetableLecture getById(Integer id) { + return findById(id) + .orElseThrow(() -> TimetableLectureNotFoundException.withDetail("id: " + id)); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index 54d1fecca9..4877ccb31e 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -3,20 +3,21 @@ import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; +import static in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureUpdateRequest.InnerTimeTableCustomLectureRequest.LectureInfo; import java.util.List; +import java.util.Objects; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import in.koreatech.koin.domain.timetableV2.exception.TimetableLectureNotFoundException; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; -import in.koreatech.koin.domain.timetableV3.controller.TimetableCustomLectureApiV3; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureCreateRequest; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; -import in.koreatech.koin.domain.timetableV3.repository.TimetableCustomLectureRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; import lombok.RequiredArgsConstructor; @@ -54,6 +55,36 @@ private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, T public TimetableLectureResponseV3 updateTimetablesCustomLecture( TimetableCustomLectureUpdateRequest request, Integer userId ) { - return null; + TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); + validateUserAuthorization(frame.getUser().getId(), userId); + TimetableLecture timetableLecture = frame.getTimetableLectures().stream() + .filter(l -> Objects.equals(l.getId(), request.timetableLecture().id())) + .findFirst() + .orElseThrow(() -> TimetableLectureNotFoundException.withDetail("id: " + request.timetableLecture().id())); + + timetableLecture.customLectureUpdate( + request.timetableLecture().classTitle(), + request.timetableLecture().professor() + ); + + timetableLecture.getTimetableCustomLectureInformations().clear(); + + List lectureInfos = request.timetableLecture().lectureInfos(); + List timetableCustomLectureInformations = lectureInfos.stream() + .map(l -> TimetableCustomLectureInformation.builder() + .timetableLecture(timetableLecture) + .startTime(l.startTime()) + .endTime(l.endTime()) + .place(l.place()) + .build() + ) + .toList(); + + for (TimetableCustomLectureInformation timetableCustomLectureInformation : timetableCustomLectureInformations) { + timetableLecture.addTimetableCustomLectureInformation(timetableCustomLectureInformation); + } + + timetableLectureRepositoryV3.save(timetableLecture); + return getTimetableLectureResponse(userId, frame); } } From ffe61c0d72acddc53452181bc1dd316b83258167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 29 Dec 2024 23:53:46 +0900 Subject: [PATCH 23/61] =?UTF-8?q?feat:=20=EC=A0=95=EA=B7=9C=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=20=EC=88=98=EC=A0=95=20=EC=9E=84=EC=8B=9C=20=EC=BB=A4?= =?UTF-8?q?=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV2/model/TimetableLecture.java | 16 +++++ .../TimetableRegularLectureUpdateRequest.java | 19 ++++++ .../TimetableRegularLectureInformation.java | 58 +++++++++++++++++++ .../TimetableRegularLectureServiceV3.java | 18 +++++- ..._timetable_regular_lecture_information.sql | 9 +++ 5 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java create mode 100644 src/main/resources/db/migration/V110__create_timetable_regular_lecture_information.sql diff --git a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java index 0bf4e51821..548c8981a7 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java @@ -10,7 +10,9 @@ import in.koreatech.koin.domain.timetable.dto.TimetableUpdateRequest; import in.koreatech.koin.domain.timetable.model.Lecture; +import in.koreatech.koin.domain.timetableV3.model.LectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; +import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import in.koreatech.koin.global.domain.BaseEntity; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; @@ -80,6 +82,9 @@ public class TimetableLecture extends BaseEntity { @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) private List timetableCustomLectureInformations = new ArrayList<>(); + @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) + private List timetableRegularLectureInformations = new ArrayList<>(); + @Builder public TimetableLecture(String classTitle, String classTime, String classPlace, String professor, String grades, String memo, boolean isDeleted, Lecture lecture, TimetableFrame timetableFrame) { @@ -135,4 +140,15 @@ public void customLectureUpdate(String classTitle, String professor) { this.classTitle = classTitle; this.professor = professor; } + + public void addTimetableRegularLectureInformation( + TimetableRegularLectureInformation timetableRegularLectureInformation + ) { + timetableRegularLectureInformations.add(timetableRegularLectureInformation); + timetableRegularLectureInformation.setTimetableLectureId(this); + } + + public void regularLectureUpdate(String classTitle) { + this.classTitle = classTitle; + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java index 9a5e1dbb04..3fb1e64669 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java @@ -4,10 +4,15 @@ import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; +import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.annotation.JsonNaming; +import in.koreatech.koin.domain.timetable.model.Lecture; +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import in.koreatech.koin.domain.timetableV3.model.LectureInformation; +import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; @@ -46,9 +51,23 @@ public record InnerTimeTableRegularLectureRequest( public record ClassPlace( @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) @Size(max = 30, message = "강의 장소의 최대 글자는 30글자입니다.") + @NotNull(message = "강의 장소를 입력해주세요.") String classPlace ) { } } + public List from(TimetableLecture timetableLecture, Lecture lecture) { + List lectureInformations = lecture.getLectureInformations(); + List response = new ArrayList<>(); + for (int index = 0; index < lectureInformations.size(); index++) { + response.add(TimetableRegularLectureInformation.builder() + .lectureInformation(lectureInformations.get(index)) + .timetableLecture(timetableLecture) + .place(this.timetableLecture.classPlaces.get(index).classPlace) + .build() + ); + } + return response; + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java new file mode 100644 index 0000000000..2294adcff4 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java @@ -0,0 +1,58 @@ +package in.koreatech.koin.domain.timetableV3.model; + +import static jakarta.persistence.GenerationType.IDENTITY; +import static lombok.AccessLevel.PROTECTED; + +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Table(name = "timetable_regular_lecture_information") +@NoArgsConstructor(access = PROTECTED) +public class TimetableRegularLectureInformation { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Integer id; + + @Column(name = "place") + private String place; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "timetable_lecture_id") + private TimetableLecture timetableLecture; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "lecture_information_id") + private LectureInformation lectureInformation; + + @Builder + public TimetableRegularLectureInformation( + String place, + TimetableLecture timetableLecture, + LectureInformation lectureInformation + ) { + this.place = place; + this.timetableLecture = timetableLecture; + this.lectureInformation = lectureInformation; + } + + public void setTimetableLectureId(TimetableLecture timetableLecture) { + this.timetableLecture = timetableLecture; + } + + public void setLectureInformationId(LectureInformation lectureInformation) { + this.lectureInformation = lectureInformation; + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index 574cafff36..47f9e9860e 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -4,6 +4,8 @@ import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; +import java.util.List; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -13,6 +15,8 @@ import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import in.koreatech.koin.domain.timetableV3.model.LectureInformation; +import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; @@ -35,7 +39,6 @@ public TimetableLectureResponseV3 createTimetablesRegularLecture( validateUserAuthorization(frame.getUser().getId(), userId); Lecture lecture = lectureRepositoryV3.getById(request.lectureId()); TimetableLecture timetableLecture = request.toTimetableLecture(frame, lecture); - // TODO. Lecture 정규화 되면 강의 시간, 장소 로직 넣어야함 timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); } @@ -50,6 +53,19 @@ private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, T public TimetableLectureResponseV3 updateTimetablesRegularLecture( TimetableRegularLectureUpdateRequest request, Integer userId ) { + TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); + validateUserAuthorization(frame.getUser().getId(), userId); + // TODO. 강의 장소 개수와 강의 시간 개수가 일치 하지 않으면 예외 던지기 + TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); + if (!timetableLecture.getLecture().getName().equals(request.timetableLecture().classTitle())) { + timetableLecture.regularLectureUpdate(request.timetableLecture().classTitle()); + } + timetableLecture.getTimetableRegularLectureInformations().clear(); + List timetableRegularLectureInformations = request.from(timetableLecture, timetableLecture.getLecture()); + for (TimetableRegularLectureInformation timetableRegularLectureInformation : timetableRegularLectureInformations) { + timetableLecture.addTimetableRegularLectureInformation(timetableRegularLectureInformation); + + } return null; } } diff --git a/src/main/resources/db/migration/V110__create_timetable_regular_lecture_information.sql b/src/main/resources/db/migration/V110__create_timetable_regular_lecture_information.sql new file mode 100644 index 0000000000..77d786bb86 --- /dev/null +++ b/src/main/resources/db/migration/V110__create_timetable_regular_lecture_information.sql @@ -0,0 +1,9 @@ +CREATE TABLE `koin`.`timetable_regular_lecture_information` +( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '고유 id', + `timetable_lecture_id` INT UNSIGNED NOT NULL COMMENT 'timetable_lecture 고유 id', + `lecture_information_id` INT UNSIGNED NOT NULL COMMENT 'lecture_information 고유 id', + `place` VARCHAR(255) NOT NULL COMMENT '강의 장소', + PRIMARY KEY (id), + INDEX(timetable_lecture_id) +) From ffc5ba0a00a1eda020fe9070acb61e94bca3ef0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Tue, 31 Dec 2024 15:22:22 +0900 Subject: [PATCH 24/61] =?UTF-8?q?feat:=20=EC=A0=95=EA=B7=9C=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=20=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/timetable/model/Lecture.java | 1 - .../timetableV2/model/TimetableLecture.java | 4 ++-- .../TimetableRegularLectureCreateRequest.java | 1 + .../TimetableRegularLectureUpdateRequest.java | 18 --------------- .../response/TimetableLectureResponseV3.java | 16 ++++++++++++- .../TimetableRegularLectureInformation.java | 3 +++ .../TimetableRegularLectureServiceV3.java | 23 +++++++++++++++---- 7 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java b/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java index 1ae5e57e93..277bd16a07 100644 --- a/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java @@ -1,6 +1,5 @@ package in.koreatech.koin.domain.timetable.model; -import static jakarta.persistence.FetchType.LAZY; import static jakarta.persistence.GenerationType.IDENTITY; import static lombok.AccessLevel.PROTECTED; diff --git a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java index 548c8981a7..2357be338a 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java @@ -79,10 +79,10 @@ public class TimetableLecture extends BaseEntity { @JoinColumn(name = "frame_id") private TimetableFrame timetableFrame; - @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) + @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture") private List timetableCustomLectureInformations = new ArrayList<>(); - @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) + @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture") private List timetableRegularLectureInformations = new ArrayList<>(); @Builder diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureCreateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureCreateRequest.java index 01d5d25e56..3d0b54d6ca 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureCreateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureCreateRequest.java @@ -25,6 +25,7 @@ public TimetableLecture toTimetableLecture(TimetableFrame frame, Lecture lecture return TimetableLecture.builder() .lecture(lecture) .timetableFrame(frame) + .grades("0") .build(); } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java index 3fb1e64669..a606472e94 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java @@ -4,15 +4,10 @@ import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; -import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.annotation.JsonNaming; -import in.koreatech.koin.domain.timetable.model.Lecture; -import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; -import in.koreatech.koin.domain.timetableV3.model.LectureInformation; -import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; @@ -57,17 +52,4 @@ public record ClassPlace( } } - public List from(TimetableLecture timetableLecture, Lecture lecture) { - List lectureInformations = lecture.getLectureInformations(); - List response = new ArrayList<>(); - for (int index = 0; index < lectureInformations.size(); index++) { - response.add(TimetableRegularLectureInformation.builder() - .lectureInformation(lectureInformations.get(index)) - .timetableLecture(timetableLecture) - .place(this.timetableLecture.classPlaces.get(index).classPlace) - .build() - ); - } - return response; - } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java index 8c22ae4f1a..a569523882 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java @@ -15,6 +15,7 @@ import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; +import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; @JsonNaming(value = SnakeCaseStrategy.class) @@ -101,6 +102,19 @@ public static List getCustomLectureInfo( .collect(Collectors.toList()); } + public static List getRegularLectureInfo( + List timetableRegularLectureInformations + ) { + return timetableRegularLectureInformations.stream() + .map(timetableRegularLectureInformation -> new LectureInfo( + calcWeek(timetableRegularLectureInformation.getLectureInformation().getStarTime()), + timetableRegularLectureInformation.getLectureInformation().getStarTime(), + timetableRegularLectureInformation.getLectureInformation().getEndTime(), + getResponsePlace(timetableRegularLectureInformation.getPlace()) + )) + .collect(Collectors.toList()); + } + private static Integer calcWeek(Integer startTime) { if (startTime != 0) { return startTime / DIVIDE_TIME_UNIT; @@ -146,7 +160,7 @@ public static List from(List lecture.getRegularNumber(), lecture.getCode(), lecture.getDesignScore(), - null, + LectureInfo.getRegularLectureInfo(timetableLecture.getTimetableRegularLectureInformations()), timetableLecture.getMemo(), lecture.getGrades(), timetableLecture.getClassTitle() == null ? lecture.getName() : timetableLecture.getClassTitle(), diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java index 2294adcff4..92078782f4 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java @@ -50,6 +50,9 @@ public TimetableRegularLectureInformation( public void setTimetableLectureId(TimetableLecture timetableLecture) { this.timetableLecture = timetableLecture; + if (!timetableLecture.getTimetableRegularLectureInformations().contains(this)) { + timetableLecture.getTimetableRegularLectureInformations().add(this); + } } public void setLectureInformationId(LectureInformation lectureInformation) { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index 47f9e9860e..69aa71da93 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -3,7 +3,9 @@ import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; +import static in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest.InnerTimeTableRegularLectureRequest.ClassPlace; +import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Service; @@ -60,12 +62,23 @@ public TimetableLectureResponseV3 updateTimetablesRegularLecture( if (!timetableLecture.getLecture().getName().equals(request.timetableLecture().classTitle())) { timetableLecture.regularLectureUpdate(request.timetableLecture().classTitle()); } + timetableLecture.getTimetableRegularLectureInformations().clear(); - List timetableRegularLectureInformations = request.from(timetableLecture, timetableLecture.getLecture()); - for (TimetableRegularLectureInformation timetableRegularLectureInformation : timetableRegularLectureInformations) { - timetableLecture.addTimetableRegularLectureInformation(timetableRegularLectureInformation); - + List lectureInformations = timetableLecture.getLecture().getLectureInformations(); + List classPlaces = request.timetableLecture().classPlaces(); + + for (int index = 0; index < lectureInformations.size(); index++) { + TimetableRegularLectureInformation timetableRegularLectureInformation = TimetableRegularLectureInformation.builder() + .timetableLecture(timetableLecture) + .lectureInformation(lectureInformations.get(index)) + .place(classPlaces.get(index).classPlace()) + .build(); + + timetableRegularLectureInformation.setLectureInformationId(lectureInformations.get(index)); + timetableRegularLectureInformation.setTimetableLectureId(timetableLecture); } - return null; + + timetableLectureRepositoryV3.save(timetableLecture); + return getTimetableLectureResponse(userId, frame); } } From d2aab0f9beefa0f9421a219c74498b41bd1f1c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Tue, 31 Dec 2024 16:05:17 +0900 Subject: [PATCH 25/61] =?UTF-8?q?fix:=20=EC=9D=91=EB=8B=B5=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV2/model/TimetableLecture.java | 4 ++-- .../response/TimetableLectureResponseV3.java | 23 ++++++++++++++++++- .../TimetableRegularLectureServiceV3.java | 4 +++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java index 2357be338a..548c8981a7 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java @@ -79,10 +79,10 @@ public class TimetableLecture extends BaseEntity { @JoinColumn(name = "frame_id") private TimetableFrame timetableFrame; - @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture") + @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) private List timetableCustomLectureInformations = new ArrayList<>(); - @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture") + @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) private List timetableRegularLectureInformations = new ArrayList<>(); @Builder diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java index a569523882..acd082d4bc 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java @@ -14,6 +14,7 @@ import in.koreatech.koin.domain.timetable.model.Lecture; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import in.koreatech.koin.domain.timetableV3.model.LectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; @@ -88,6 +89,7 @@ public record LectureInfo( String place ) { private static final Integer DIVIDE_TIME_UNIT = 100; + private static final String EMPTY_PLACE = ""; public static List getCustomLectureInfo( List timetableCustomLectureInformations @@ -115,6 +117,18 @@ public static List getRegularLectureInfo( .collect(Collectors.toList()); } + public static List getLectureInfo(List lectureInformations) { + return lectureInformations.stream() + .map(lectureInformation -> new LectureInfo( + calcWeek(lectureInformation.getStarTime()), + lectureInformation.getStarTime(), + lectureInformation.getEndTime(), + EMPTY_PLACE + ) + ) + .collect(Collectors.toList()); + } + private static Integer calcWeek(Integer startTime) { if (startTime != 0) { return startTime / DIVIDE_TIME_UNIT; @@ -160,7 +174,7 @@ public static List from(List lecture.getRegularNumber(), lecture.getCode(), lecture.getDesignScore(), - LectureInfo.getRegularLectureInfo(timetableLecture.getTimetableRegularLectureInformations()), + getLectureInfo(timetableLecture, lecture), timetableLecture.getMemo(), lecture.getGrades(), timetableLecture.getClassTitle() == null ? lecture.getName() : timetableLecture.getClassTitle(), @@ -174,6 +188,13 @@ public static List from(List } return InnerTimetableLectureResponses; } + + public static List getLectureInfo(TimetableLecture timetableLecture, Lecture lecture) { + if (timetableLecture.getTimetableRegularLectureInformations().isEmpty()) { + return LectureInfo.getLectureInfo(lecture.getLectureInformations()); + } + return LectureInfo.getRegularLectureInfo(timetableLecture.getTimetableRegularLectureInformations()); + } } public static TimetableLectureResponseV3 of(TimetableFrame frame, int grades, int totalGrades) { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index 69aa71da93..3142762eb3 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -57,7 +57,9 @@ public TimetableLectureResponseV3 updateTimetablesRegularLecture( ) { TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); validateUserAuthorization(frame.getUser().getId(), userId); - // TODO. 강의 장소 개수와 강의 시간 개수가 일치 하지 않으면 예외 던지기 + /* + * TODO. 강의 장소 개수와 강의 시간 개수가 일치 하지 않으면 예외 던지기 + * TODO. Lecture id와 dto 내부의 lecutreId가 일치하지 않은 경우 예외 던지기*/ TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); if (!timetableLecture.getLecture().getName().equals(request.timetableLecture().classTitle())) { timetableLecture.regularLectureUpdate(request.timetableLecture().classTitle()); From acd6ce55503e93633b2452dc6911ef8d3c80681e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Tue, 31 Dec 2024 16:49:10 +0900 Subject: [PATCH 26/61] =?UTF-8?q?docs:=20TODO=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TimetableRegularLectureControllerV3.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java index f6037ac092..31aa828efc 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java @@ -31,6 +31,7 @@ public ResponseEntity createTimetablesRegularLecture return ResponseEntity.ok(response); } + // TODO. 업데이트 된 정규 강의 데이터 수기로 옮기기 (프로시저로 못 옮김) @PutMapping("/v3/timetables/lecture/regular") public ResponseEntity updateTimetablesRegularLecture( @Valid @RequestBody TimetableRegularLectureUpdateRequest request, From 77b6feffb174db9875c1d8adb5be04d5bc06adb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Tue, 31 Dec 2024 17:08:51 +0900 Subject: [PATCH 27/61] =?UTF-8?q?feat:=20=EC=8B=9C=EA=B0=84=ED=91=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/TimetableLectureServiceV3.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java index ea993a3863..870aad10c5 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java @@ -1,15 +1,32 @@ package in.koreatech.koin.domain.timetableV3.service; +import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; +import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; +import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; + import org.springframework.stereotype.Service; +import in.koreatech.koin.domain.timetableV2.dto.response.TimetableLectureResponse; +import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; +import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; import lombok.RequiredArgsConstructor; @Service @RequiredArgsConstructor public class TimetableLectureServiceV3 { + private final TimetableFrameRepositoryV3 timetableFrameRepositoryV3; + public TimetableLectureResponseV3 getTimetableLecture(Integer timetableFrameId, Integer userId) { - return null; + TimetableFrame frame = timetableFrameRepositoryV3.getById(timetableFrameId); + validateUserAuthorization(frame.getUser().getId(), userId); + return getTimetableLectureResponse(userId, frame); + } + + private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, TimetableFrame timetableFrame) { + int grades = calculateGradesMainFrame(timetableFrame); + int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); + return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); } } From a1c0885bad43ff112c4f2adbff692c45da9644c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Tue, 31 Dec 2024 17:10:53 +0900 Subject: [PATCH 28/61] =?UTF-8?q?feat:=20timetableV3=20=EC=8A=A4=EC=9B=A8?= =?UTF-8?q?=EA=B1=B0=20=EA=B7=B8=EB=A3=B9=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/global/config/swagger/SwaggerGroupConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/global/config/swagger/SwaggerGroupConfig.java b/src/main/java/in/koreatech/koin/global/config/swagger/SwaggerGroupConfig.java index de048156e2..117d18626e 100644 --- a/src/main/java/in/koreatech/koin/global/config/swagger/SwaggerGroupConfig.java +++ b/src/main/java/in/koreatech/koin/global/config/swagger/SwaggerGroupConfig.java @@ -60,7 +60,8 @@ public GroupedOpenApi userApi() { "in.koreatech.koin.domain.user", "in.koreatech.koin.domain.student", "in.koreatech.koin.domain.timetable", - "in.koreatech.koin.domain.timetableV2" + "in.koreatech.koin.domain.timetableV2", + "in.koreatech.koin.domain.timetableV3" }; return createGroupedOpenApi("4. User API", packagesPath); From e7db2f5fb05b9af4c60d5f3b767bc5960009f667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Thu, 2 Jan 2025 14:09:10 +0900 Subject: [PATCH 29/61] =?UTF-8?q?feat:=20TimetableLectureInformation=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20flyway=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/TimetableLectureInformation.java | 62 +++++++++++++++++++ ..._timetable_custom_lecture_information.sql} | 2 +- ...110__create_lecture_information_table.sql} | 2 +- ...timetable_regular_lecture_information.sql} | 2 +- ...__create_timetable_lecture_information.sql | 10 +++ 5 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java rename src/main/resources/db/migration/{V108__create_timetable_custom_lecture_information.sql => V109__create_timetable_custom_lecture_information.sql} (83%) rename src/main/resources/db/migration/{V109__create_lecture_information_table.sql => V110__create_lecture_information_table.sql} (77%) rename src/main/resources/db/migration/{V110__create_timetable_regular_lecture_information.sql => V111__create_timetable_regular_lecture_information.sql} (84%) create mode 100644 src/main/resources/db/migration/V112__create_timetable_lecture_information.sql diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java new file mode 100644 index 0000000000..f487f5d81e --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java @@ -0,0 +1,62 @@ +package in.koreatech.koin.domain.timetableV3.model; + +import static jakarta.persistence.FetchType.LAZY; +import static jakarta.persistence.GenerationType.IDENTITY; +import static lombok.AccessLevel.PROTECTED; + +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Table(name = "timetable_lecture_information") +@NoArgsConstructor(access = PROTECTED) +public class TimetableLectureInformation { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Integer id; + + @Column(name = "start_time") + private Integer startTime; + + @Column(name = "end_time") + private Integer endTime; + + @Column(name = "place", length = 255) + private String place; + + @ManyToOne(fetch = LAZY) + @JoinColumn(name = "lecture_information_id") + private LectureInformation lectureInformation; + + @ManyToOne(fetch = LAZY) + @JoinColumn(name = "timetable_lecture_id") + private TimetableLecture timetableLecture; + + @Builder + private TimetableLectureInformation( + Integer id, + Integer startTime, + Integer endTime, + String place, + LectureInformation lectureInformation, + TimetableLecture timetableLecture + ) { + this.id = id; + this.startTime = startTime; + this.endTime = endTime; + this.place = place; + this.lectureInformation = lectureInformation; + this.timetableLecture = timetableLecture; + } +} diff --git a/src/main/resources/db/migration/V108__create_timetable_custom_lecture_information.sql b/src/main/resources/db/migration/V109__create_timetable_custom_lecture_information.sql similarity index 83% rename from src/main/resources/db/migration/V108__create_timetable_custom_lecture_information.sql rename to src/main/resources/db/migration/V109__create_timetable_custom_lecture_information.sql index efefff9c9d..8a11e5eacd 100644 --- a/src/main/resources/db/migration/V108__create_timetable_custom_lecture_information.sql +++ b/src/main/resources/db/migration/V109__create_timetable_custom_lecture_information.sql @@ -1,4 +1,4 @@ -CREATE TABLE `koin`.`timetable_custom_lecture_information` ( +CREATE TABLE IF NOT EXISTS `koin`.`timetable_custom_lecture_information` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '고유 id', `timetable_lecture_id` INT UNSIGNED NOT NULL COMMENT 'timetableLecture id', `start_time` INT UNSIGNED NOT NULL COMMENT '시작 시간', diff --git a/src/main/resources/db/migration/V109__create_lecture_information_table.sql b/src/main/resources/db/migration/V110__create_lecture_information_table.sql similarity index 77% rename from src/main/resources/db/migration/V109__create_lecture_information_table.sql rename to src/main/resources/db/migration/V110__create_lecture_information_table.sql index 41acca0486..907aeaf1a5 100644 --- a/src/main/resources/db/migration/V109__create_lecture_information_table.sql +++ b/src/main/resources/db/migration/V110__create_lecture_information_table.sql @@ -1,4 +1,4 @@ -CREATE TABLE `koin`.`lecture_information`( +CREATE TABLE IF NOT EXISTS `koin`.`lecture_information`( `id` int UNSIGNED NOT NULL AUTO_INCREMENT, `lecture_id` int UNSIGNED NOT NULL, `start_time` int NULL, diff --git a/src/main/resources/db/migration/V110__create_timetable_regular_lecture_information.sql b/src/main/resources/db/migration/V111__create_timetable_regular_lecture_information.sql similarity index 84% rename from src/main/resources/db/migration/V110__create_timetable_regular_lecture_information.sql rename to src/main/resources/db/migration/V111__create_timetable_regular_lecture_information.sql index 77d786bb86..1f839f5ba3 100644 --- a/src/main/resources/db/migration/V110__create_timetable_regular_lecture_information.sql +++ b/src/main/resources/db/migration/V111__create_timetable_regular_lecture_information.sql @@ -1,4 +1,4 @@ -CREATE TABLE `koin`.`timetable_regular_lecture_information` +CREATE TABLE IF NOT EXISTS `koin`.`timetable_regular_lecture_information` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '고유 id', `timetable_lecture_id` INT UNSIGNED NOT NULL COMMENT 'timetable_lecture 고유 id', diff --git a/src/main/resources/db/migration/V112__create_timetable_lecture_information.sql b/src/main/resources/db/migration/V112__create_timetable_lecture_information.sql new file mode 100644 index 0000000000..4deb817e02 --- /dev/null +++ b/src/main/resources/db/migration/V112__create_timetable_lecture_information.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS `koin`.`timetable_lecture_information` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '고유 id', + `start_time` INT UNSIGNED NULL COMMENT '커스텀 강의 시작 시간', + `end_time` INT UNSIGNED NULL COMMENT '커스텀 강의 종료 시간', + `place` VARCHAR(255) NULL COMMENT '강의 장소', + `lecture_information_id` INT UNSIGNED NULL COMMENT 'lecture_information 고유 id', + `timetable_lecture_id` INT UNSIGNED NOT NULL COMMENT 'timetable_lecture 고유 id', + PRIMARY KEY (id), + INDEX(timetable_lecture_id) +) From 719ca373a8d0de80b16a7dee0d6e1c99ce7ba794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Thu, 2 Jan 2025 14:48:50 +0900 Subject: [PATCH 30/61] =?UTF-8?q?fix:=20TimetableLEctureInformation?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=BD=94=EB=93=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV2/model/TimetableLecture.java | 9 ++++ .../TimetableCustomLectureCreateRequest.java | 6 +-- .../TimetableCustomLectureUpdateRequest.java | 13 +++++ .../response/TimetableLectureResponseV3.java | 15 +++--- .../model/TimetableLectureInformation.java | 8 +++ .../TimetableCustomLectureServiceV3.java | 52 +++++++++++++++++-- .../TimetableRegularLectureServiceV3.java | 47 ++++++++++++++--- 7 files changed, 127 insertions(+), 23 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java index 548c8981a7..c3ec3e9fe8 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java @@ -12,6 +12,7 @@ import in.koreatech.koin.domain.timetable.model.Lecture; import in.koreatech.koin.domain.timetableV3.model.LectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; +import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import in.koreatech.koin.global.domain.BaseEntity; import jakarta.persistence.CascadeType; @@ -85,6 +86,9 @@ public class TimetableLecture extends BaseEntity { @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) private List timetableRegularLectureInformations = new ArrayList<>(); + @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) + private List timetableLectureInformations = new ArrayList<>(); + @Builder public TimetableLecture(String classTitle, String classTime, String classPlace, String professor, String grades, String memo, boolean isDeleted, Lecture lecture, TimetableFrame timetableFrame) { @@ -129,6 +133,11 @@ public void undelete() { this.isDeleted = false; } + public void addTimetableLectureInformation(TimetableLectureInformation timetableLectureInformation) { + this.timetableLectureInformations.add(timetableLectureInformation); + timetableLectureInformation.setTimetableLectureId(this); + } + public void addTimetableCustomLectureInformation( TimetableCustomLectureInformation timetableCustomLectureInformation ) { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java index c698df49a5..7f2cebe06f 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java @@ -11,7 +11,7 @@ import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; -import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; +import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; @@ -76,9 +76,9 @@ public TimetableLecture toTimetableLecture(TimetableFrame frame) { .build(); } - public List toTimetableCustomLectureInformations() { + public List toTimetableLectureInformations() { return timetableLecture.lectureInfos.stream() - .map(lectureInfo -> TimetableCustomLectureInformation.builder() + .map(lectureInfo -> TimetableLectureInformation.builder() .startTime(lectureInfo.startTime) .endTime(lectureInfo.endTime) .place(lectureInfo.place) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java index db6de32ca0..0f0b039e01 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java @@ -5,9 +5,11 @@ import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; import java.util.List; +import java.util.stream.Collectors; import com.fasterxml.jackson.databind.annotation.JsonNaming; +import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; @@ -57,4 +59,15 @@ public record LectureInfo( } } + + public List toTimetableLectureInformations() { + return timetableLecture.lectureInfos.stream() + .map(lectureInfo -> TimetableLectureInformation.builder() + .startTime(lectureInfo.startTime) + .endTime(lectureInfo.endTime) + .place(lectureInfo.place) + .build() + ) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java index acd082d4bc..81bf05da41 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java @@ -16,6 +16,7 @@ import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; import in.koreatech.koin.domain.timetableV3.model.LectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; +import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; @@ -92,9 +93,9 @@ public record LectureInfo( private static final String EMPTY_PLACE = ""; public static List getCustomLectureInfo( - List timetableCustomLectureInformations + List timetableLectureInformations ) { - return timetableCustomLectureInformations.stream() + return timetableLectureInformations.stream() .map(timetableCustomLectureInformation -> new LectureInfo( calcWeek(timetableCustomLectureInformation.getStartTime()), timetableCustomLectureInformation.getStartTime(), @@ -105,9 +106,9 @@ public static List getCustomLectureInfo( } public static List getRegularLectureInfo( - List timetableRegularLectureInformations + List timetableLectureInformations ) { - return timetableRegularLectureInformations.stream() + return timetableLectureInformations.stream() .map(timetableRegularLectureInformation -> new LectureInfo( calcWeek(timetableRegularLectureInformation.getLectureInformation().getStarTime()), timetableRegularLectureInformation.getLectureInformation().getStarTime(), @@ -158,7 +159,7 @@ public static List from(List null, null, null, - LectureInfo.getCustomLectureInfo(timetableLecture.getTimetableCustomLectureInformations()), + LectureInfo.getCustomLectureInfo(timetableLecture.getTimetableLectureInformations()), timetableLecture.getMemo(), timetableLecture.getGrades(), timetableLecture.getClassTitle(), @@ -190,10 +191,10 @@ public static List from(List } public static List getLectureInfo(TimetableLecture timetableLecture, Lecture lecture) { - if (timetableLecture.getTimetableRegularLectureInformations().isEmpty()) { + if (timetableLecture.getTimetableLectureInformations().isEmpty()) { return LectureInfo.getLectureInfo(lecture.getLectureInformations()); } - return LectureInfo.getRegularLectureInfo(timetableLecture.getTimetableRegularLectureInformations()); + return LectureInfo.getRegularLectureInfo(timetableLecture.getTimetableLectureInformations()); } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java index f487f5d81e..0d83b5c766 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java @@ -59,4 +59,12 @@ private TimetableLectureInformation( this.lectureInformation = lectureInformation; this.timetableLecture = timetableLecture; } + + public void setTimetableLectureId(TimetableLecture timetableLecture) { + this.timetableLecture = timetableLecture; + } + + public void setLectureInformationId(LectureInformation lectureInformation) { + this.lectureInformation = lectureInformation; + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index 4877ccb31e..35f5f26b3e 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -3,21 +3,18 @@ import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; -import static in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureUpdateRequest.InnerTimeTableCustomLectureRequest.LectureInfo; import java.util.List; -import java.util.Objects; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import in.koreatech.koin.domain.timetableV2.exception.TimetableLectureNotFoundException; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureCreateRequest; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; -import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; +import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; import lombok.RequiredArgsConstructor; @@ -30,6 +27,51 @@ public class TimetableCustomLectureServiceV3 { private final TimetableFrameRepositoryV3 timetableFrameRepositoryV3; private final TimetableLectureRepositoryV3 timetableLectureRepositoryV3; + @Transactional + public TimetableLectureResponseV3 createTimetablesCustomLecture( + TimetableCustomLectureCreateRequest request, Integer userId + ) { + TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); + validateUserAuthorization(frame.getUser().getId(), userId); + TimetableLecture timetableLecture = request.toTimetableLecture(frame); + List timetableLectureInformations = request.toTimetableLectureInformations(); + for (TimetableLectureInformation timetableLectureInformation : timetableLectureInformations) { + timetableLecture.addTimetableLectureInformation(timetableLectureInformation); + } + timetableLectureRepositoryV3.save(timetableLecture); + return getTimetableLectureResponse(userId, frame); + } + + private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, TimetableFrame timetableFrame) { + int grades = calculateGradesMainFrame(timetableFrame); + int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); + return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); + } + + @Transactional + public TimetableLectureResponseV3 updateTimetablesCustomLecture( + TimetableCustomLectureUpdateRequest request, Integer userId + ) { + TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); + validateUserAuthorization(frame.getUser().getId(), userId); + TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); + + timetableLecture.customLectureUpdate( + request.timetableLecture().classTitle(), + request.timetableLecture().professor() + ); + + timetableLecture.getTimetableLectureInformations().clear(); + List timetableLectureInformations = request.toTimetableLectureInformations(); + for (TimetableLectureInformation timetableLectureInformation : timetableLectureInformations) { + timetableLecture.addTimetableLectureInformation(timetableLectureInformation); + } + + timetableLectureRepositoryV3.save(timetableLecture); + return getTimetableLectureResponse(userId, frame); + } + + /* @Transactional public TimetableLectureResponseV3 createTimetablesCustomLecture( TimetableCustomLectureCreateRequest request, Integer userId @@ -86,5 +128,5 @@ public TimetableLectureResponseV3 updateTimetablesCustomLecture( timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); - } + }*/ } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index 3142762eb3..5631ccf129 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -5,7 +5,6 @@ import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; import static in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest.InnerTimeTableRegularLectureRequest.ClassPlace; -import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Service; @@ -18,6 +17,7 @@ import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.model.LectureInformation; +import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; @@ -58,8 +58,8 @@ public TimetableLectureResponseV3 updateTimetablesRegularLecture( TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); validateUserAuthorization(frame.getUser().getId(), userId); /* - * TODO. 강의 장소 개수와 강의 시간 개수가 일치 하지 않으면 예외 던지기 - * TODO. Lecture id와 dto 내부의 lecutreId가 일치하지 않은 경우 예외 던지기*/ + * TODO. 강의 장소 개수와 강의 시간 개수가 일치 하지 않으면 예외 던지기 + * TODO. Lecture id와 dto 내부의 lecutreId가 일치하지 않은 경우 예외 던지기*/ TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); if (!timetableLecture.getLecture().getName().equals(request.timetableLecture().classTitle())) { timetableLecture.regularLectureUpdate(request.timetableLecture().classTitle()); @@ -70,17 +70,48 @@ public TimetableLectureResponseV3 updateTimetablesRegularLecture( List classPlaces = request.timetableLecture().classPlaces(); for (int index = 0; index < lectureInformations.size(); index++) { - TimetableRegularLectureInformation timetableRegularLectureInformation = TimetableRegularLectureInformation.builder() - .timetableLecture(timetableLecture) - .lectureInformation(lectureInformations.get(index)) + TimetableLectureInformation timetableLectureInformation = TimetableLectureInformation.builder() .place(classPlaces.get(index).classPlace()) .build(); - timetableRegularLectureInformation.setLectureInformationId(lectureInformations.get(index)); - timetableRegularLectureInformation.setTimetableLectureId(timetableLecture); + timetableLecture.addTimetableLectureInformation(timetableLectureInformation); + timetableLectureInformation.setLectureInformationId(lectureInformations.get(index)); } timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); } + + // @Transactional + // public TimetableLectureResponseV3 updateTimetablesRegularLecture( + // TimetableRegularLectureUpdateRequest request, Integer userId + // ) { + // TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); + // validateUserAuthorization(frame.getUser().getId(), userId); + // /* + // * TODO. 강의 장소 개수와 강의 시간 개수가 일치 하지 않으면 예외 던지기 + // * TODO. Lecture id와 dto 내부의 lecutreId가 일치하지 않은 경우 예외 던지기*/ + // TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); + // if (!timetableLecture.getLecture().getName().equals(request.timetableLecture().classTitle())) { + // timetableLecture.regularLectureUpdate(request.timetableLecture().classTitle()); + // } + // + // timetableLecture.getTimetableRegularLectureInformations().clear(); + // List lectureInformations = timetableLecture.getLecture().getLectureInformations(); + // List classPlaces = request.timetableLecture().classPlaces(); + // + // for (int index = 0; index < lectureInformations.size(); index++) { + // TimetableRegularLectureInformation timetableRegularLectureInformation = TimetableRegularLectureInformation.builder() + // .timetableLecture(timetableLecture) + // .lectureInformation(lectureInformations.get(index)) + // .place(classPlaces.get(index).classPlace()) + // .build(); + // + // timetableRegularLectureInformation.setLectureInformationId(lectureInformations.get(index)); + // timetableRegularLectureInformation.setTimetableLectureId(timetableLecture); + // } + // + // timetableLectureRepositoryV3.save(timetableLecture); + // return getTimetableLectureResponse(userId, frame); + // } } From 0c1e5cbdf2fb2f7a5f3ddf8a2eb65b17329eeaae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Thu, 2 Jan 2025 14:49:23 +0900 Subject: [PATCH 31/61] =?UTF-8?q?chore:=20=EC=9D=B4=EC=A0=84=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimetableCustomLectureServiceV3.java | 59 ------------------- .../TimetableRegularLectureServiceV3.java | 33 ----------- 2 files changed, 92 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index 35f5f26b3e..9a9eca37ba 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -70,63 +70,4 @@ public TimetableLectureResponseV3 updateTimetablesCustomLecture( timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); } - - /* - @Transactional - public TimetableLectureResponseV3 createTimetablesCustomLecture( - TimetableCustomLectureCreateRequest request, Integer userId - ) { - TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); - validateUserAuthorization(frame.getUser().getId(), userId); - TimetableLecture timetableLecture = request.toTimetableLecture(frame); - List timetableCustomLectureInformations = request.toTimetableCustomLectureInformations(); - for (TimetableCustomLectureInformation timetableCustomLectureInformation : timetableCustomLectureInformations) { - timetableLecture.addTimetableCustomLectureInformation(timetableCustomLectureInformation); - } - timetableLectureRepositoryV3.save(timetableLecture); - return getTimetableLectureResponse(userId, frame); - } - - private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, TimetableFrame timetableFrame) { - int grades = calculateGradesMainFrame(timetableFrame); - int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); - return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); - } - - @Transactional - public TimetableLectureResponseV3 updateTimetablesCustomLecture( - TimetableCustomLectureUpdateRequest request, Integer userId - ) { - TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); - validateUserAuthorization(frame.getUser().getId(), userId); - TimetableLecture timetableLecture = frame.getTimetableLectures().stream() - .filter(l -> Objects.equals(l.getId(), request.timetableLecture().id())) - .findFirst() - .orElseThrow(() -> TimetableLectureNotFoundException.withDetail("id: " + request.timetableLecture().id())); - - timetableLecture.customLectureUpdate( - request.timetableLecture().classTitle(), - request.timetableLecture().professor() - ); - - timetableLecture.getTimetableCustomLectureInformations().clear(); - - List lectureInfos = request.timetableLecture().lectureInfos(); - List timetableCustomLectureInformations = lectureInfos.stream() - .map(l -> TimetableCustomLectureInformation.builder() - .timetableLecture(timetableLecture) - .startTime(l.startTime()) - .endTime(l.endTime()) - .place(l.place()) - .build() - ) - .toList(); - - for (TimetableCustomLectureInformation timetableCustomLectureInformation : timetableCustomLectureInformations) { - timetableLecture.addTimetableCustomLectureInformation(timetableCustomLectureInformation); - } - - timetableLectureRepositoryV3.save(timetableLecture); - return getTimetableLectureResponse(userId, frame); - }*/ } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index 5631ccf129..8b16225a03 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -81,37 +81,4 @@ public TimetableLectureResponseV3 updateTimetablesRegularLecture( timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); } - - // @Transactional - // public TimetableLectureResponseV3 updateTimetablesRegularLecture( - // TimetableRegularLectureUpdateRequest request, Integer userId - // ) { - // TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); - // validateUserAuthorization(frame.getUser().getId(), userId); - // /* - // * TODO. 강의 장소 개수와 강의 시간 개수가 일치 하지 않으면 예외 던지기 - // * TODO. Lecture id와 dto 내부의 lecutreId가 일치하지 않은 경우 예외 던지기*/ - // TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); - // if (!timetableLecture.getLecture().getName().equals(request.timetableLecture().classTitle())) { - // timetableLecture.regularLectureUpdate(request.timetableLecture().classTitle()); - // } - // - // timetableLecture.getTimetableRegularLectureInformations().clear(); - // List lectureInformations = timetableLecture.getLecture().getLectureInformations(); - // List classPlaces = request.timetableLecture().classPlaces(); - // - // for (int index = 0; index < lectureInformations.size(); index++) { - // TimetableRegularLectureInformation timetableRegularLectureInformation = TimetableRegularLectureInformation.builder() - // .timetableLecture(timetableLecture) - // .lectureInformation(lectureInformations.get(index)) - // .place(classPlaces.get(index).classPlace()) - // .build(); - // - // timetableRegularLectureInformation.setLectureInformationId(lectureInformations.get(index)); - // timetableRegularLectureInformation.setTimetableLectureId(timetableLecture); - // } - // - // timetableLectureRepositoryV3.save(timetableLecture); - // return getTimetableLectureResponse(userId, frame); - // } } From e862005793a2a7c0e69d3ba6265862094eda4a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Thu, 2 Jan 2025 15:18:53 +0900 Subject: [PATCH 32/61] =?UTF-8?q?chore:=20=EC=9D=B4=EC=A0=84=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20flyway=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV2/model/TimetableLecture.java | 23 ------- .../response/TimetableLectureResponseV3.java | 2 - .../TimetableCustomLectureInformation.java | 61 ------------------- .../TimetableRegularLectureInformation.java | 61 ------------------- .../TimetableCustomLectureRepositoryV3.java | 8 --- .../service/TimetableLectureServiceV3.java | 1 - .../TimetableRegularLectureServiceV3.java | 3 +- ...e_timetable_custom_lecture_information.sql | 9 --- ..._create_timetable_lecture_information.sql} | 0 ...V110__create_lecture_information_table.sql | 8 +-- ..._timetable_regular_lecture_information.sql | 9 --- 11 files changed, 5 insertions(+), 180 deletions(-) delete mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableCustomLectureInformation.java delete mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java delete mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableCustomLectureRepositoryV3.java delete mode 100644 src/main/resources/db/migration/V109__create_timetable_custom_lecture_information.sql rename src/main/resources/db/migration/{V112__create_timetable_lecture_information.sql => V109__create_timetable_lecture_information.sql} (100%) delete mode 100644 src/main/resources/db/migration/V111__create_timetable_regular_lecture_information.sql diff --git a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java index c3ec3e9fe8..4a25375120 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java @@ -10,10 +10,7 @@ import in.koreatech.koin.domain.timetable.dto.TimetableUpdateRequest; import in.koreatech.koin.domain.timetable.model.Lecture; -import in.koreatech.koin.domain.timetableV3.model.LectureInformation; -import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; -import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import in.koreatech.koin.global.domain.BaseEntity; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; @@ -80,12 +77,6 @@ public class TimetableLecture extends BaseEntity { @JoinColumn(name = "frame_id") private TimetableFrame timetableFrame; - @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) - private List timetableCustomLectureInformations = new ArrayList<>(); - - @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) - private List timetableRegularLectureInformations = new ArrayList<>(); - @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) private List timetableLectureInformations = new ArrayList<>(); @@ -138,25 +129,11 @@ public void addTimetableLectureInformation(TimetableLectureInformation timetable timetableLectureInformation.setTimetableLectureId(this); } - public void addTimetableCustomLectureInformation( - TimetableCustomLectureInformation timetableCustomLectureInformation - ) { - timetableCustomLectureInformations.add(timetableCustomLectureInformation); - timetableCustomLectureInformation.setTimetableLectureId(this); - } - public void customLectureUpdate(String classTitle, String professor) { this.classTitle = classTitle; this.professor = professor; } - public void addTimetableRegularLectureInformation( - TimetableRegularLectureInformation timetableRegularLectureInformation - ) { - timetableRegularLectureInformations.add(timetableRegularLectureInformation); - timetableRegularLectureInformation.setTimetableLectureId(this); - } - public void regularLectureUpdate(String classTitle) { this.classTitle = classTitle; } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java index 81bf05da41..8aee578504 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java @@ -15,9 +15,7 @@ import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; import in.koreatech.koin.domain.timetableV3.model.LectureInformation; -import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; -import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; @JsonNaming(value = SnakeCaseStrategy.class) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableCustomLectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableCustomLectureInformation.java deleted file mode 100644 index 07e356d282..0000000000 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableCustomLectureInformation.java +++ /dev/null @@ -1,61 +0,0 @@ -package in.koreatech.koin.domain.timetableV3.model; - -import static jakarta.persistence.GenerationType.IDENTITY; -import static lombok.AccessLevel.PROTECTED; - -import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; -import jakarta.validation.constraints.NotNull; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Getter -@Table(name = "timetable_custom_lecture_information") -@NoArgsConstructor(access = PROTECTED) -public class TimetableCustomLectureInformation { - - @Id - @GeneratedValue(strategy = IDENTITY) - private Integer id; - - @NotNull - @Column(name = "start_time", nullable = false) - private Integer startTime; - - @NotNull - @Column(name = "end_time", nullable = false) - private Integer endTime; - - @Column(name = "place") - private String place; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "timetable_lecture_id") - private TimetableLecture timetableLecture; - - @Builder - public TimetableCustomLectureInformation( - Integer startTime, - Integer endTime, - String place, - TimetableLecture timetableLecture - ) { - this.startTime = startTime; - this.endTime = endTime; - this.place = place; - this.timetableLecture = timetableLecture; - } - - public void setTimetableLectureId(TimetableLecture timetableLecture) { - this.timetableLecture = timetableLecture; - } -} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java deleted file mode 100644 index 92078782f4..0000000000 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableRegularLectureInformation.java +++ /dev/null @@ -1,61 +0,0 @@ -package in.koreatech.koin.domain.timetableV3.model; - -import static jakarta.persistence.GenerationType.IDENTITY; -import static lombok.AccessLevel.PROTECTED; - -import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Getter -@Table(name = "timetable_regular_lecture_information") -@NoArgsConstructor(access = PROTECTED) -public class TimetableRegularLectureInformation { - - @Id - @GeneratedValue(strategy = IDENTITY) - private Integer id; - - @Column(name = "place") - private String place; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "timetable_lecture_id") - private TimetableLecture timetableLecture; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "lecture_information_id") - private LectureInformation lectureInformation; - - @Builder - public TimetableRegularLectureInformation( - String place, - TimetableLecture timetableLecture, - LectureInformation lectureInformation - ) { - this.place = place; - this.timetableLecture = timetableLecture; - this.lectureInformation = lectureInformation; - } - - public void setTimetableLectureId(TimetableLecture timetableLecture) { - this.timetableLecture = timetableLecture; - if (!timetableLecture.getTimetableRegularLectureInformations().contains(this)) { - timetableLecture.getTimetableRegularLectureInformations().add(this); - } - } - - public void setLectureInformationId(LectureInformation lectureInformation) { - this.lectureInformation = lectureInformation; - } -} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableCustomLectureRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableCustomLectureRepositoryV3.java deleted file mode 100644 index 930d903c5a..0000000000 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableCustomLectureRepositoryV3.java +++ /dev/null @@ -1,8 +0,0 @@ -package in.koreatech.koin.domain.timetableV3.repository; - -import org.springframework.data.repository.Repository; - -import in.koreatech.koin.domain.timetableV3.model.TimetableCustomLectureInformation; - -public interface TimetableCustomLectureRepositoryV3 extends Repository { -} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java index 870aad10c5..85b2fd523f 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java @@ -6,7 +6,6 @@ import org.springframework.stereotype.Service; -import in.koreatech.koin.domain.timetableV2.dto.response.TimetableLectureResponse; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index 8b16225a03..44f241412a 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -18,7 +18,6 @@ import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.model.LectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; -import in.koreatech.koin.domain.timetableV3.model.TimetableRegularLectureInformation; import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; @@ -65,7 +64,7 @@ public TimetableLectureResponseV3 updateTimetablesRegularLecture( timetableLecture.regularLectureUpdate(request.timetableLecture().classTitle()); } - timetableLecture.getTimetableRegularLectureInformations().clear(); + timetableLecture.getTimetableLectureInformations().clear(); List lectureInformations = timetableLecture.getLecture().getLectureInformations(); List classPlaces = request.timetableLecture().classPlaces(); diff --git a/src/main/resources/db/migration/V109__create_timetable_custom_lecture_information.sql b/src/main/resources/db/migration/V109__create_timetable_custom_lecture_information.sql deleted file mode 100644 index 8a11e5eacd..0000000000 --- a/src/main/resources/db/migration/V109__create_timetable_custom_lecture_information.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE IF NOT EXISTS `koin`.`timetable_custom_lecture_information` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '고유 id', - `timetable_lecture_id` INT UNSIGNED NOT NULL COMMENT 'timetableLecture id', - `start_time` INT UNSIGNED NOT NULL COMMENT '시작 시간', - `end_time` INT UNSIGNED NOT NULL COMMENT '종료 시간', - `place` VARCHAR(255) NULL COMMENT '장소', - PRIMARY KEY (id), - INDEX(timetable_lecture_id) -) diff --git a/src/main/resources/db/migration/V112__create_timetable_lecture_information.sql b/src/main/resources/db/migration/V109__create_timetable_lecture_information.sql similarity index 100% rename from src/main/resources/db/migration/V112__create_timetable_lecture_information.sql rename to src/main/resources/db/migration/V109__create_timetable_lecture_information.sql diff --git a/src/main/resources/db/migration/V110__create_lecture_information_table.sql b/src/main/resources/db/migration/V110__create_lecture_information_table.sql index 907aeaf1a5..5751f428a7 100644 --- a/src/main/resources/db/migration/V110__create_lecture_information_table.sql +++ b/src/main/resources/db/migration/V110__create_lecture_information_table.sql @@ -1,8 +1,8 @@ CREATE TABLE IF NOT EXISTS `koin`.`lecture_information`( - `id` int UNSIGNED NOT NULL AUTO_INCREMENT, - `lecture_id` int UNSIGNED NOT NULL, - `start_time` int NULL, - `end_time` int NULL, + `id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '고유 id', + `lecture_id` int UNSIGNED NOT NULL COMMENT 'lecture 고유 id', + `start_time` int NULL COMMENT '정규 강의 시작 시간', + `end_time` int NULL COMMENT '정규 강의 마감 시간', PRIMARY KEY (`id`), index (`lecture_id`) ); diff --git a/src/main/resources/db/migration/V111__create_timetable_regular_lecture_information.sql b/src/main/resources/db/migration/V111__create_timetable_regular_lecture_information.sql deleted file mode 100644 index 1f839f5ba3..0000000000 --- a/src/main/resources/db/migration/V111__create_timetable_regular_lecture_information.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE IF NOT EXISTS `koin`.`timetable_regular_lecture_information` -( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '고유 id', - `timetable_lecture_id` INT UNSIGNED NOT NULL COMMENT 'timetable_lecture 고유 id', - `lecture_information_id` INT UNSIGNED NOT NULL COMMENT 'lecture_information 고유 id', - `place` VARCHAR(255) NOT NULL COMMENT '강의 장소', - PRIMARY KEY (id), - INDEX(timetable_lecture_id) -) From c119aa3739e74028470086579f48d582c296580a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Thu, 2 Jan 2025 19:22:31 +0900 Subject: [PATCH 33/61] =?UTF-8?q?feat:=20=EA=B0=95=EC=9D=98=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EC=B2=B4=ED=81=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...imetableLectureTimeDuplicateException.java | 19 ++++++ .../TimetableCustomLectureServiceV3.java | 3 + .../validation/TimetableLectureValidate.java | 68 +++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/exception/TimetableLectureTimeDuplicateException.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/validation/TimetableLectureValidate.java diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/exception/TimetableLectureTimeDuplicateException.java b/src/main/java/in/koreatech/koin/domain/timetableV3/exception/TimetableLectureTimeDuplicateException.java new file mode 100644 index 0000000000..973240d0e1 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/exception/TimetableLectureTimeDuplicateException.java @@ -0,0 +1,19 @@ +package in.koreatech.koin.domain.timetableV3.exception; + +import in.koreatech.koin.global.exception.KoinIllegalArgumentException; + +public class TimetableLectureTimeDuplicateException extends KoinIllegalArgumentException { + public static final String DEFAULT_MESSAGE = "강의 시간이 겹칩니다."; + + public TimetableLectureTimeDuplicateException(String message) { + super(message); + } + + public TimetableLectureTimeDuplicateException(String message, String detail) { + super(message, detail); + } + + public static TimetableLectureTimeDuplicateException withDetail(String detail) { + return new TimetableLectureTimeDuplicateException(DEFAULT_MESSAGE, detail); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index 9a9eca37ba..e648a76611 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -3,6 +3,7 @@ import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; +import static in.koreatech.koin.domain.timetableV3.validation.TimetableLectureValidate.checkDuplicateTimetableLectureTime; import java.util.List; @@ -35,6 +36,7 @@ public TimetableLectureResponseV3 createTimetablesCustomLecture( validateUserAuthorization(frame.getUser().getId(), userId); TimetableLecture timetableLecture = request.toTimetableLecture(frame); List timetableLectureInformations = request.toTimetableLectureInformations(); + checkDuplicateTimetableLectureTime(frame.getTimetableLectures(), timetableLectureInformations); for (TimetableLectureInformation timetableLectureInformation : timetableLectureInformations) { timetableLecture.addTimetableLectureInformation(timetableLectureInformation); } @@ -63,6 +65,7 @@ public TimetableLectureResponseV3 updateTimetablesCustomLecture( timetableLecture.getTimetableLectureInformations().clear(); List timetableLectureInformations = request.toTimetableLectureInformations(); + checkDuplicateTimetableLectureTime(frame.getTimetableLectures(), timetableLectureInformations); for (TimetableLectureInformation timetableLectureInformation : timetableLectureInformations) { timetableLecture.addTimetableLectureInformation(timetableLectureInformation); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/validation/TimetableLectureValidate.java b/src/main/java/in/koreatech/koin/domain/timetableV3/validation/TimetableLectureValidate.java new file mode 100644 index 0000000000..fb4dfd9d98 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/validation/TimetableLectureValidate.java @@ -0,0 +1,68 @@ +package in.koreatech.koin.domain.timetableV3.validation; + +import static lombok.AccessLevel.PRIVATE; + +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; +import in.koreatech.koin.domain.timetableV3.exception.TimetableLectureTimeDuplicateException; +import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = PRIVATE) +public class TimetableLectureValidate { + + public static void checkDuplicateTimetableLectureTime( + List timetableLectures, List timetableLectureInformations + ) { + Queue classInformations = getClassInformations(timetableLectures); + + for (ClassInformation classInformation : classInformations) { + for (TimetableLectureInformation timetableLectureInformation : timetableLectureInformations) { + int startTime = timetableLectureInformation.getLectureInformation() != null ? + timetableLectureInformation.getLectureInformation().getStarTime() : + timetableLectureInformation.getStartTime(); + int endTime = timetableLectureInformation.getLectureInformation() != null ? + timetableLectureInformation.getLectureInformation().getEndTime() : + timetableLectureInformation.getEndTime(); + + if (classInformation.checkBetweenTime(startTime, endTime)) { + throw new TimetableLectureTimeDuplicateException( + String.format("%s 강의 시간과 중복됩니다", classInformation.classTitle)); + } + } + } + } + + private static Queue getClassInformations(List timetableLectures) { + Queue classInformations = new LinkedList<>(); + + for (TimetableLecture timetableLecture : timetableLectures) { + List timetableLectureInformations = timetableLecture.getTimetableLectureInformations(); + + for (TimetableLectureInformation timetableLectureInformation : timetableLectureInformations) { + int startTime = timetableLectureInformation.getLectureInformation() != null ? + timetableLectureInformation.getLectureInformation().getStarTime() : + timetableLectureInformation.getStartTime(); + int endTime = timetableLectureInformation.getLectureInformation() != null ? + timetableLectureInformation.getLectureInformation().getEndTime() : + timetableLectureInformation.getEndTime(); + + classInformations.add(new ClassInformation(timetableLecture.getClassTitle(), startTime, endTime)); + } + } + return classInformations; + } + + public record ClassInformation( + String classTitle, + int startTime, + int endTime + ) { + public boolean checkBetweenTime(int startTime, int endTime) { + return this.startTime <= startTime || this.endTime <= endTime; + } + } +} From 8c545c0032c14f1e53e82fe60d837e551791da9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Thu, 2 Jan 2025 19:22:38 +0900 Subject: [PATCH 34/61] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=EC=8B=9C?= =?UTF-8?q?=EC=A0=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ray_class_time_normalization_procedure.sql | 53 ++++++++++++++ ...ray_class_time_normalization_procedure.sql | 71 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/main/resources/db/migration/V111__add_array_class_time_normalization_procedure.sql create mode 100644 src/main/resources/db/migration/V112__add_call_array_class_time_normalization_procedure.sql diff --git a/src/main/resources/db/migration/V111__add_array_class_time_normalization_procedure.sql b/src/main/resources/db/migration/V111__add_array_class_time_normalization_procedure.sql new file mode 100644 index 0000000000..b5d5c6c643 --- /dev/null +++ b/src/main/resources/db/migration/V111__add_array_class_time_normalization_procedure.sql @@ -0,0 +1,53 @@ +DELIMITER $$ + +CREATE PROCEDURE array_class_time_normalization ( + IN_LECTURE_ID int unsigned +) +BEGIN + -- 변수 선언 + DECLARE IN_CLASS_TIME varchar(255); + DECLARE current_class_time int; + DECLARE prev_class_time int DEFAULT NULL; + DECLARE start_class_time int DEFAULT NULL; + DECLARE end_class_time int DEFAULT NULL; + DECLARE idx int DEFAULT 1; + DECLARE count int DEFAULT 1; + + -- class_time 가져오기 + SELECT class_time INTO IN_CLASS_TIME + FROM lectures + WHERE id = IN_LECTURE_ID; + + -- 대괄호 앞 뒤 삭제 + SET IN_CLASS_TIME = REPLACE(REPLACE(IN_CLASS_TIME, '[', ''), ']', ''); + + -- 강의 시간이 있는 경우에만 로직 실행 + IF LENGTH(IN_CLASS_TIME) != 0 THEN + -- 총 실행 횟수, (현재 길이 - 콤마를 없앴을 때의 길이 + 1 = 총 시간 개수) + SET count = LENGTH(IN_CLASS_TIME) - LENGTH(REPLACE(IN_CLASS_TIME, ',', '')) + 1; + WHILE idx <= count DO + -- 인덱스에 해당하는 시간 가져오기 + SET current_class_time = CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(IN_CLASS_TIME, ',', idx), ',', -1) AS UNSIGNED); + + -- 초기 시작 시간 설정 및 연속 시간 체크 + IF prev_class_time IS NULL OR current_class_time != prev_class_time + 1 THEN + IF start_class_time IS NOT NULL THEN + INSERT INTO lecture_information (lecture_id, start_time, end_time) VALUES (IN_LECTURE_ID, start_class_time, end_class_time); + END IF; + SET start_class_time = current_class_time; + END IF; + + -- 다음 시간 저장 + SET end_class_time = current_class_time; + SET prev_class_time = current_class_time; + SET idx = idx + 1; + END WHILE; + + -- 마지막 범위 추가 + IF start_class_time IS NOT NULL THEN + INSERT INTO lecture_information (lecture_id, start_time, end_time) VALUES (IN_LECTURE_ID, start_class_time, end_class_time); + END IF; + END IF; + +END $$ +DELIMITER ; diff --git a/src/main/resources/db/migration/V112__add_call_array_class_time_normalization_procedure.sql b/src/main/resources/db/migration/V112__add_call_array_class_time_normalization_procedure.sql new file mode 100644 index 0000000000..cbbc154ae0 --- /dev/null +++ b/src/main/resources/db/migration/V112__add_call_array_class_time_normalization_procedure.sql @@ -0,0 +1,71 @@ +DELIMITER $$ + +CREATE PROCEDURE call_array_class_time_normalization( + IN_SEMESTER_DATE VARCHAR(10) +) +BEGIN + DECLARE done INT DEFAULT 0; + DECLARE lecture_id INT; + DECLARE flag INT DEFAULT 0; + + -- 커서 선언 + DECLARE cur CURSOR FOR + SELECT id FROM lectures + where semester_date = IN_SEMESTER_DATE; + + -- 종료 핸들러 정의 + DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1; + + -- 커서 열기 + OPEN cur; + + lecture_loop: LOOP + FETCH cur INTO lecture_id; -- 여기서 반환값이 없으면 에러가 발생 -> 이를 종료 핸들러가 캐치 + IF flag THEN -- 데이터가 없으면 루프 종료 + LEAVE lecture_loop; + END IF; + + CALL array_class_time_normalization(lecture_id); +END LOOP; + + -- 커서 닫기 + CLOSE cur; +END$$ + +DELIMITER ; + +-- 2019 +CALL call_array_class_time_normalization("20191"); +CALL call_array_class_time_normalization("2019-여름"); +CALL call_array_class_time_normalization("20192"); +CALL call_array_class_time_normalization("2019-겨울"); + +-- 2020 +CALL call_array_class_time_normalization("20201"); +CALL call_array_class_time_normalization("2020-여름"); +CALL call_array_class_time_normalization("20202"); +CALL call_array_class_time_normalization("2020-겨울"); + +-- 2021 +CALL call_array_class_time_normalization("20211"); +CALL call_array_class_time_normalization("2021-여름"); +CALL call_array_class_time_normalization("20212"); +CALL call_array_class_time_normalization("2021-겨울"); + +-- 2022 +CALL call_array_class_time_normalization("20221"); +CALL call_array_class_time_normalization("2022-여름"); +CALL call_array_class_time_normalization("20222"); +CALL call_array_class_time_normalization("2022-겨울"); + +-- 2023 +CALL call_array_class_time_normalization("20231"); +CALL call_array_class_time_normalization("2023-여름"); +CALL call_array_class_time_normalization("20232"); +CALL call_array_class_time_normalization("2023-겨울"); + +-- 2024 +CALL call_array_class_time_normalization("20241"); +CALL call_array_class_time_normalization("2024-여름"); +CALL call_array_class_time_normalization("20242"); +CALL call_array_class_time_normalization("2024-겨울"); From 4aa16568bfa5d2970fcbeab4a4053d8c0aa438fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Thu, 2 Jan 2025 23:41:09 +0900 Subject: [PATCH 35/61] =?UTF-8?q?chore:=20=EC=A0=95=EA=B7=9C=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=20API=20=EC=A0=95=EA=B7=9C=ED=99=94=20=EB=A1=A4?= =?UTF-8?q?=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/LectureResponseV3.java | 58 +++++++++++++++---- .../repository/LectureRepositoryV3.java | 8 --- .../timetableV3/service/LectureServiceV3.java | 5 +- 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java index 1519046a22..24c14a0b75 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java @@ -5,12 +5,14 @@ import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; import com.fasterxml.jackson.databind.annotation.JsonNaming; import in.koreatech.koin.domain.timetable.model.Lecture; -import in.koreatech.koin.domain.timetableV3.model.LectureInformation; import io.swagger.v3.oas.annotations.media.Schema; @JsonNaming(value = SnakeCaseStrategy.class) @@ -66,22 +68,58 @@ public record LectureInfo( @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) Integer endTime ) { - public static List from(List lectureInformations) { + private static final Integer DIVIDE_TIME_UNIT = 100; + + public static List from(String classTime) { + List classTimes = parseToIntegerList(classTime); List response = new ArrayList<>(); - for (LectureInformation lectureInformation : lectureInformations) { + if (!classTimes.isEmpty()) { + Integer prevTime = null; + Integer startTime = null; + Integer endTime = null; + + for (Integer time : classTimes) { + if (Objects.isNull(prevTime) || time != prevTime + 1) { + addLectureInfo(response, startTime, endTime); + startTime = time; + } + endTime = time; + prevTime = time; + } + + addLectureInfo(response, startTime, endTime); + } + return response; + } + + private static void addLectureInfo(List response, Integer startTime, Integer endTime) { + if (!Objects.isNull(startTime)) { response.add(new LectureInfo( - lectureInformation.getStarTime() / 100, - lectureInformation.getStarTime(), - lectureInformation.getEndTime()) - ); + calcWeek(startTime), + startTime, + endTime + )); } + } - return response; + private static Integer calcWeek(Integer startTime) { + if (startTime != 0) { + return startTime / DIVIDE_TIME_UNIT; + } + return 0; + } + + private static List parseToIntegerList(String classTime) { + return Stream.of(classTime.replaceAll("[\\[\\]]", "").split(",")) + .map(String::strip) + .filter(time -> !time.isEmpty()) + .map(Integer::parseInt) + .toList(); } } - public static LectureResponseV3 of(Lecture lecture, List lectureInformations) { + public static LectureResponseV3 from(Lecture lecture) { return new LectureResponseV3( lecture.getId(), lecture.getCode(), @@ -95,7 +133,7 @@ public static LectureResponseV3 of(Lecture lecture, List lec lecture.getIsEnglish(), lecture.getDesignScore(), lecture.getIsElearning(), - LectureInfo.from(lectureInformations) + LectureInfo.from(lecture.getClassTime()) ); } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java index 1db0031250..2a60ab6412 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java @@ -20,12 +20,4 @@ default Lecture getById(Integer id) { } List findBySemester(String semesterDate); - - @Query(""" - SELECT l - FROM Lecture l - LEFT JOIN FETCH l.lectureInformations - WHERE l.semester = :semesterDate - """) - List findLecturesWithInformations(@Param("semesterDate") String semesterDate); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java index 88f4f5bbcc..c756e425b4 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java @@ -16,9 +16,8 @@ public class LectureServiceV3 { private final LectureRepositoryV3 lectureRepositoryV3; public List getLectures(String semesterDate) { - List lectures = lectureRepositoryV3.findLecturesWithInformations(semesterDate); - return lectures.stream() - .map(lecture -> LectureResponseV3.of(lecture, lecture.getLectureInformations())) + return lectureRepositoryV3.findBySemester(semesterDate).stream() + .map(LectureResponseV3::from) .toList(); } } From 0dd3afdd42123f9001841389f30c7c00d29c4dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 3 Jan 2025 10:55:52 +0900 Subject: [PATCH 36/61] =?UTF-8?q?chore:=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EA=B0=95=EC=9D=98=20API=20=EC=A0=95=EA=B7=9C=ED=99=94=20?= =?UTF-8?q?=EB=A1=A4=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV2/model/TimetableLecture.java | 15 ++-- .../timetableV3/dto/request/LectureInfo.java | 25 +++++++ .../TimetableCustomLectureCreateRequest.java | 30 ++------ .../TimetableCustomLectureUpdateRequest.java | 24 +------ .../dto/response/LectureResponseV3.java | 21 +----- .../response/TimetableLectureResponseV3.java | 70 +++++++++---------- .../TimetableCustomLectureServiceV3.java | 30 +++----- .../TimetableRegularLectureServiceV3.java | 38 +++------- .../timetableV3/utils/ClassPlaceUtils.java | 44 ++++++++++++ .../timetableV3/utils/ClassTimeUtils.java | 48 +++++++++++++ 10 files changed, 187 insertions(+), 158 deletions(-) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/LectureInfo.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java diff --git a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java index 4a25375120..7047f7e056 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java @@ -124,17 +124,18 @@ public void undelete() { this.isDeleted = false; } - public void addTimetableLectureInformation(TimetableLectureInformation timetableLectureInformation) { - this.timetableLectureInformations.add(timetableLectureInformation); - timetableLectureInformation.setTimetableLectureId(this); - } - - public void customLectureUpdate(String classTitle, String professor) { + public void customLectureUpdate(String classTitle, String professor, String classTime, String classPlace) { this.classTitle = classTitle; this.professor = professor; + this.classTime = classTime; + this.classPlace = classPlace; } - public void regularLectureUpdate(String classTitle) { + public void regularLectureTitleUpdate(String classTitle) { this.classTitle = classTitle; } + + public void regularLectureClassPlaceUpdate(String classPlace) { + this.classPlace = classPlace; + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/LectureInfo.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/LectureInfo.java new file mode 100644 index 0000000000..595eac2ed5 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/LectureInfo.java @@ -0,0 +1,25 @@ +package in.koreatech.koin.domain.timetableV3.dto.request; + +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; + +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; + +@JsonNaming(value = SnakeCaseStrategy.class) +public record LectureInfo( + @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) + Integer startTime, + + @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) + Integer endTime, + + @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) + @Size(max = 30, message = "강의 장소의 최대 글자는 30글자입니다.") + String place +) { + +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java index 7f2cebe06f..0e624833a0 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java @@ -1,17 +1,17 @@ package in.koreatech.koin.domain.timetableV3.dto.request; import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.joinClassPlaces; +import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.joinClassTimes; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; import java.util.List; -import java.util.stream.Collectors; import com.fasterxml.jackson.databind.annotation.JsonNaming; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; -import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; @@ -50,20 +50,7 @@ public record InnerTimeTableCustomLectureRequest( @Size(max = 200, message = "메모는 200자 이하로 입력해주세요.") String memo ) { - @JsonNaming(value = SnakeCaseStrategy.class) - public record LectureInfo( - @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) - Integer startTime, - @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) - Integer endTime, - - @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) - @Size(max = 30, message = "강의 장소의 최대 글자는 30글자입니다.") - String place - ) { - - } } public TimetableLecture toTimetableLecture(TimetableFrame frame) { @@ -72,18 +59,9 @@ public TimetableLecture toTimetableLecture(TimetableFrame frame) { .professor(timetableLecture.professor) .grades(timetableLecture.grades) .memo(timetableLecture.memo) + .classTime(joinClassTimes(timetableLecture.lectureInfos)) + .classPlace(joinClassPlaces(timetableLecture.lectureInfos)) .timetableFrame(frame) .build(); } - - public List toTimetableLectureInformations() { - return timetableLecture.lectureInfos.stream() - .map(lectureInfo -> TimetableLectureInformation.builder() - .startTime(lectureInfo.startTime) - .endTime(lectureInfo.endTime) - .place(lectureInfo.place) - .build() - ) - .collect(Collectors.toList()); - } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java index 0f0b039e01..02c9243b85 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java @@ -4,6 +4,7 @@ import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -44,30 +45,7 @@ public record InnerTimeTableCustomLectureRequest( @Size(max = 30, message = "교수명의 최대 글자는 30글자 입니다.") String professor ) { - @JsonNaming(value = SnakeCaseStrategy.class) - public record LectureInfo( - @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) - Integer startTime, - @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) - Integer endTime, - - @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) - @Size(max = 30, message = "강의 장소의 최대 글자는 30글자입니다.") - String place - ) { - - } } - public List toTimetableLectureInformations() { - return timetableLecture.lectureInfos.stream() - .map(lectureInfo -> TimetableLectureInformation.builder() - .startTime(lectureInfo.startTime) - .endTime(lectureInfo.endTime) - .place(lectureInfo.place) - .build() - ) - .collect(Collectors.toList()); - } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java index 24c14a0b75..8cf687c00e 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java @@ -1,14 +1,14 @@ package in.koreatech.koin.domain.timetableV3.dto.response; import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.calcWeek; +import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.parseToIntegerList; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.stream.Stream; import com.fasterxml.jackson.databind.annotation.JsonNaming; @@ -68,8 +68,6 @@ public record LectureInfo( @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) Integer endTime ) { - private static final Integer DIVIDE_TIME_UNIT = 100; - public static List from(String classTime) { List classTimes = parseToIntegerList(classTime); List response = new ArrayList<>(); @@ -102,21 +100,6 @@ private static void addLectureInfo(List response, Integer startTime )); } } - - private static Integer calcWeek(Integer startTime) { - if (startTime != 0) { - return startTime / DIVIDE_TIME_UNIT; - } - return 0; - } - - private static List parseToIntegerList(String classTime) { - return Stream.of(classTime.replaceAll("[\\[\\]]", "").split(",")) - .map(String::strip) - .filter(time -> !time.isEmpty()) - .map(Integer::parseInt) - .toList(); - } } public static LectureResponseV3 from(Lecture lecture) { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java index 8aee578504..6ee08dbba4 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java @@ -1,6 +1,9 @@ package in.koreatech.koin.domain.timetableV3.dto.response; import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.parseToStringList; +import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.calcWeek; +import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.parseToIntegerList; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; @@ -14,7 +17,6 @@ import in.koreatech.koin.domain.timetable.model.Lecture; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; -import in.koreatech.koin.domain.timetableV3.model.LectureInformation; import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; @@ -87,7 +89,6 @@ public record LectureInfo( @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) String place ) { - private static final Integer DIVIDE_TIME_UNIT = 100; private static final String EMPTY_PLACE = ""; public static List getCustomLectureInfo( @@ -103,36 +104,38 @@ public static List getCustomLectureInfo( .collect(Collectors.toList()); } - public static List getRegularLectureInfo( - List timetableLectureInformations - ) { - return timetableLectureInformations.stream() - .map(timetableRegularLectureInformation -> new LectureInfo( - calcWeek(timetableRegularLectureInformation.getLectureInformation().getStarTime()), - timetableRegularLectureInformation.getLectureInformation().getStarTime(), - timetableRegularLectureInformation.getLectureInformation().getEndTime(), - getResponsePlace(timetableRegularLectureInformation.getPlace()) - )) - .collect(Collectors.toList()); - } - - public static List getLectureInfo(List lectureInformations) { - return lectureInformations.stream() - .map(lectureInformation -> new LectureInfo( - calcWeek(lectureInformation.getStarTime()), - lectureInformation.getStarTime(), - lectureInformation.getEndTime(), - EMPTY_PLACE - ) - ) - .collect(Collectors.toList()); + public static List getRegularLectureInfo(String classTime, String classPlace) { + List classTimes = parseToIntegerList(classTime); + List classPlaces = parseToStringList(classPlace); + List response = new ArrayList<>(); + int index = 0; + + if (!classTimes.isEmpty()) { + Integer prevTime = null; + Integer startTime = null; + Integer endTime = null; + + for (Integer time : classTimes) { + if (Objects.isNull(prevTime) || time != prevTime + 1) { + addLectureInfo(response, startTime, endTime, classPlaces.get(index)); + startTime = time; + index++; + } + endTime = time; + prevTime = time; + } + + addLectureInfo(response, startTime, endTime, classPlaces.get(index)); + } + return response; } - private static Integer calcWeek(Integer startTime) { - if (startTime != 0) { - return startTime / DIVIDE_TIME_UNIT; + private static void addLectureInfo( + List response, Integer startTime, Integer endTime, String classPlace + ) { + if (!Objects.isNull(startTime)) { + response.add(new LectureInfo(calcWeek(startTime), startTime, endTime, classPlace)); } - return 0; } private static String getResponsePlace(String place) { @@ -173,7 +176,7 @@ public static List from(List lecture.getRegularNumber(), lecture.getCode(), lecture.getDesignScore(), - getLectureInfo(timetableLecture, lecture), + LectureInfo.getRegularLectureInfo(lecture.getClassTime(), timetableLecture.getClassPlace()), timetableLecture.getMemo(), lecture.getGrades(), timetableLecture.getClassTitle() == null ? lecture.getName() : timetableLecture.getClassTitle(), @@ -187,13 +190,6 @@ public static List from(List } return InnerTimetableLectureResponses; } - - public static List getLectureInfo(TimetableLecture timetableLecture, Lecture lecture) { - if (timetableLecture.getTimetableLectureInformations().isEmpty()) { - return LectureInfo.getLectureInfo(lecture.getLectureInformations()); - } - return LectureInfo.getRegularLectureInfo(timetableLecture.getTimetableLectureInformations()); - } } public static TimetableLectureResponseV3 of(TimetableFrame frame, int grades, int totalGrades) { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index e648a76611..fe3fb6c373 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -3,6 +3,8 @@ import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; +import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.joinClassPlaces; +import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.joinClassTimes; import static in.koreatech.koin.domain.timetableV3.validation.TimetableLectureValidate.checkDuplicateTimetableLectureTime; import java.util.List; @@ -35,21 +37,10 @@ public TimetableLectureResponseV3 createTimetablesCustomLecture( TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); validateUserAuthorization(frame.getUser().getId(), userId); TimetableLecture timetableLecture = request.toTimetableLecture(frame); - List timetableLectureInformations = request.toTimetableLectureInformations(); - checkDuplicateTimetableLectureTime(frame.getTimetableLectures(), timetableLectureInformations); - for (TimetableLectureInformation timetableLectureInformation : timetableLectureInformations) { - timetableLecture.addTimetableLectureInformation(timetableLectureInformation); - } timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); } - private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, TimetableFrame timetableFrame) { - int grades = calculateGradesMainFrame(timetableFrame); - int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); - return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); - } - @Transactional public TimetableLectureResponseV3 updateTimetablesCustomLecture( TimetableCustomLectureUpdateRequest request, Integer userId @@ -60,17 +51,18 @@ public TimetableLectureResponseV3 updateTimetablesCustomLecture( timetableLecture.customLectureUpdate( request.timetableLecture().classTitle(), - request.timetableLecture().professor() + request.timetableLecture().professor(), + joinClassTimes(request.timetableLecture().lectureInfos()), + joinClassPlaces(request.timetableLecture().lectureInfos()) ); - timetableLecture.getTimetableLectureInformations().clear(); - List timetableLectureInformations = request.toTimetableLectureInformations(); - checkDuplicateTimetableLectureTime(frame.getTimetableLectures(), timetableLectureInformations); - for (TimetableLectureInformation timetableLectureInformation : timetableLectureInformations) { - timetableLecture.addTimetableLectureInformation(timetableLectureInformation); - } - timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); } + + private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, TimetableFrame timetableFrame) { + int grades = calculateGradesMainFrame(timetableFrame); + int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); + return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index 44f241412a..dd557e016c 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -3,9 +3,7 @@ import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; -import static in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest.InnerTimeTableRegularLectureRequest.ClassPlace; - -import java.util.List; +import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.parseToString; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -16,8 +14,6 @@ import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureCreateRequest; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; -import in.koreatech.koin.domain.timetableV3.model.LectureInformation; -import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; @@ -44,40 +40,28 @@ public TimetableLectureResponseV3 createTimetablesRegularLecture( return getTimetableLectureResponse(userId, frame); } - private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, TimetableFrame timetableFrame) { - int grades = calculateGradesMainFrame(timetableFrame); - int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); - return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); - } - @Transactional public TimetableLectureResponseV3 updateTimetablesRegularLecture( TimetableRegularLectureUpdateRequest request, Integer userId ) { TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); validateUserAuthorization(frame.getUser().getId(), userId); - /* - * TODO. 강의 장소 개수와 강의 시간 개수가 일치 하지 않으면 예외 던지기 - * TODO. Lecture id와 dto 내부의 lecutreId가 일치하지 않은 경우 예외 던지기*/ + TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); if (!timetableLecture.getLecture().getName().equals(request.timetableLecture().classTitle())) { - timetableLecture.regularLectureUpdate(request.timetableLecture().classTitle()); + timetableLecture.regularLectureTitleUpdate(request.timetableLecture().classTitle()); } - timetableLecture.getTimetableLectureInformations().clear(); - List lectureInformations = timetableLecture.getLecture().getLectureInformations(); - List classPlaces = request.timetableLecture().classPlaces(); - - for (int index = 0; index < lectureInformations.size(); index++) { - TimetableLectureInformation timetableLectureInformation = TimetableLectureInformation.builder() - .place(classPlaces.get(index).classPlace()) - .build(); - - timetableLecture.addTimetableLectureInformation(timetableLectureInformation); - timetableLectureInformation.setLectureInformationId(lectureInformations.get(index)); - } + String classPlace = parseToString(request.timetableLecture().classPlaces()); + timetableLecture.regularLectureClassPlaceUpdate(classPlace); timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); } + + private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, TimetableFrame timetableFrame) { + int grades = calculateGradesMainFrame(timetableFrame); + int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); + return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java new file mode 100644 index 0000000000..18cd74407a --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java @@ -0,0 +1,44 @@ +package in.koreatech.koin.domain.timetableV3.utils; + +import static in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest.InnerTimeTableRegularLectureRequest.ClassPlace; +import static lombok.AccessLevel.PRIVATE; + +import java.util.List; +import java.util.stream.Stream; + +import in.koreatech.koin.domain.timetableV3.dto.request.LectureInfo; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = PRIVATE) +public class ClassPlaceUtils { + + private static final String CLASSPLACE_SEPARATOR = ", "; + + public static List parseToStringList(String classPlace) { + return Stream.of(classPlace.split(",")) + .map(String::strip) + .filter(place -> !place.isEmpty()) + .toList(); + } + + public static String parseToString(List classPlaces) { + StringBuilder classPlaceSegment = new StringBuilder(); + for (int index = 0; index < classPlaces.size(); index++) { + if (index > 0) { + classPlaceSegment.append(", "); + } + classPlaceSegment.append(classPlaces.get(index).classPlace()); + } + return classPlaceSegment.toString(); + } + + public static String joinClassPlaces(List lectureInfos) { + StringBuilder classPlaces = new StringBuilder(); + + for (int index = 0; index < lectureInfos.size(); index++) { + if (index > 0) classPlaces.append(CLASSPLACE_SEPARATOR); + classPlaces.append(lectureInfos.get(index).place()); + } + return classPlaces.toString(); + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java new file mode 100644 index 0000000000..4388f1be61 --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java @@ -0,0 +1,48 @@ +package in.koreatech.koin.domain.timetableV3.utils; + +import static lombok.AccessLevel.PRIVATE; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import in.koreatech.koin.domain.timetableV3.dto.request.LectureInfo; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = PRIVATE) +public class ClassTimeUtils { + + private static final Integer DIVIDE_TIME_UNIT = 100; + private static final Integer CLASSTIME_SEPARATOR = -1; + + public static List parseToIntegerList(String classTime) { + return Stream.of(classTime.replaceAll("[\\[\\]]", "").split(",")) + .map(String::strip) + .filter(time -> !time.isEmpty()) + .map(Integer::parseInt) + .toList(); + } + + public static Integer calcWeek(Integer startTime) { + if (startTime != 0) { + return startTime / DIVIDE_TIME_UNIT; + } + return 0; + } + + public static String joinClassTimes(List lectureInfos) { + List classTimes = new ArrayList<>(); + + for (int index = 0; index < lectureInfos.size(); index++) { + if (index > 0) classTimes.add(CLASSTIME_SEPARATOR); + + int startTime = lectureInfos.get(index).startTime(); + int endTime = lectureInfos.get(index).endTime(); + + while (startTime > endTime) { + classTimes.add(startTime++); + } + } + return classTimes.toString(); + } +} From 21e22372d84cdf3483efdff344c82b3b1ae34713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 3 Jan 2025 19:26:24 +0900 Subject: [PATCH 37/61] =?UTF-8?q?chore:=20=EC=9D=91=EB=8B=B5=EA=B0=92=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/timetable/model/Lecture.java | 9 -- .../timetableV2/model/TimetableLecture.java | 18 +-- .../TimetableRegularLectureControllerV3.java | 1 - ...ctureInfo.java => RequestLectureInfo.java} | 2 +- .../TimetableCustomLectureCreateRequest.java | 2 +- .../TimetableCustomLectureUpdateRequest.java | 5 +- .../dto/response/LectureResponseV3.java | 6 +- .../dto/response/ResponseLectureInfo.java | 122 ++++++++++++++++++ .../response/TimetableLectureResponseV3.java | 85 +----------- .../timetableV3/model/LectureInformation.java | 46 ------- .../model/TimetableLectureInformation.java | 70 ---------- .../LectureInformationRepositoryV3.java | 11 -- .../TimetableCustomLectureServiceV3.java | 4 - .../TimetableRegularLectureServiceV3.java | 12 +- .../timetableV3/utils/ClassPlaceUtils.java | 14 +- .../timetableV3/utils/ClassTimeUtils.java | 9 +- .../validation/TimetableLectureValidate.java | 68 ---------- 17 files changed, 154 insertions(+), 330 deletions(-) rename src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/{LectureInfo.java => RequestLectureInfo.java} (96%) create mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/ResponseLectureInfo.java delete mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java delete mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java delete mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureInformationRepositoryV3.java delete mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/validation/TimetableLectureValidate.java diff --git a/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java b/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java index 277bd16a07..a786613af6 100644 --- a/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetable/model/Lecture.java @@ -3,16 +3,10 @@ import static jakarta.persistence.GenerationType.IDENTITY; import static lombok.AccessLevel.PROTECTED; -import java.util.ArrayList; -import java.util.List; - -import in.koreatech.koin.domain.timetableV3.model.LectureInformation; -import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; -import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -92,9 +86,6 @@ public class Lecture { @Column(name = "class_time", nullable = false) private String classTime; - @OneToMany(cascade = CascadeType.ALL, mappedBy = "lecture", orphanRemoval = true) - private List lectureInformations = new ArrayList<>(); - @Builder public Lecture( String semester, diff --git a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java index 7047f7e056..590a7ef9c5 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java @@ -3,16 +3,11 @@ import static jakarta.persistence.GenerationType.IDENTITY; import static lombok.AccessLevel.PROTECTED; -import java.util.ArrayList; -import java.util.List; - import org.hibernate.annotations.Where; import in.koreatech.koin.domain.timetable.dto.TimetableUpdateRequest; import in.koreatech.koin.domain.timetable.model.Lecture; -import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import in.koreatech.koin.global.domain.BaseEntity; -import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -21,7 +16,6 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.Lob; import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -77,9 +71,6 @@ public class TimetableLecture extends BaseEntity { @JoinColumn(name = "frame_id") private TimetableFrame timetableFrame; - @OneToMany(cascade = CascadeType.ALL, mappedBy = "timetableLecture", orphanRemoval = true) - private List timetableLectureInformations = new ArrayList<>(); - @Builder public TimetableLecture(String classTitle, String classTime, String classPlace, String professor, String grades, String memo, boolean isDeleted, Lecture lecture, TimetableFrame timetableFrame) { @@ -131,11 +122,10 @@ public void customLectureUpdate(String classTitle, String professor, String clas this.classPlace = classPlace; } - public void regularLectureTitleUpdate(String classTitle) { - this.classTitle = classTitle; - } - - public void regularLectureClassPlaceUpdate(String classPlace) { + public void regularLectureUpdate(String classTitle, String classPlace) { + if (!lecture.getName().equals(classTitle)) { + this.classTitle = classTitle; + } this.classPlace = classPlace; } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java index 31aa828efc..f6037ac092 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureControllerV3.java @@ -31,7 +31,6 @@ public ResponseEntity createTimetablesRegularLecture return ResponseEntity.ok(response); } - // TODO. 업데이트 된 정규 강의 데이터 수기로 옮기기 (프로시저로 못 옮김) @PutMapping("/v3/timetables/lecture/regular") public ResponseEntity updateTimetablesRegularLecture( @Valid @RequestBody TimetableRegularLectureUpdateRequest request, diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/LectureInfo.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/RequestLectureInfo.java similarity index 96% rename from src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/LectureInfo.java rename to src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/RequestLectureInfo.java index 595eac2ed5..f300433ccd 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/LectureInfo.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/RequestLectureInfo.java @@ -10,7 +10,7 @@ import jakarta.validation.constraints.Size; @JsonNaming(value = SnakeCaseStrategy.class) -public record LectureInfo( +public record RequestLectureInfo( @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) Integer startTime, diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java index 0e624833a0..b3701f6878 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java @@ -36,7 +36,7 @@ public record InnerTimeTableCustomLectureRequest( @Valid @Schema(description = "커스텀 강의 시간 정보", requiredMode = REQUIRED) - List lectureInfos, + List lectureInfos, @Schema(description = "교수명", example = "교수명", requiredMode = NOT_REQUIRED) @Size(max = 30, message = "교수명의 최대 글자는 30글자 입니다.") diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java index 02c9243b85..08aef517d6 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java @@ -4,13 +4,10 @@ import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; -import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import com.fasterxml.jackson.databind.annotation.JsonNaming; -import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; @@ -39,7 +36,7 @@ public record InnerTimeTableCustomLectureRequest( @Valid @Schema(description = "커스텀 강의 시간 정보", requiredMode = REQUIRED) - List lectureInfos, + List lectureInfos, @Schema(description = "교수명", example = "교수명", requiredMode = NOT_REQUIRED) @Size(max = 30, message = "교수명의 최대 글자는 30글자 입니다.") diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java index 8cf687c00e..f4db9d4aae 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java @@ -93,11 +93,7 @@ public static List from(String classTime) { private static void addLectureInfo(List response, Integer startTime, Integer endTime) { if (!Objects.isNull(startTime)) { - response.add(new LectureInfo( - calcWeek(startTime), - startTime, - endTime - )); + response.add(new LectureInfo(calcWeek(startTime), startTime, endTime)); } } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/ResponseLectureInfo.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/ResponseLectureInfo.java new file mode 100644 index 0000000000..14b77b0cdf --- /dev/null +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/ResponseLectureInfo.java @@ -0,0 +1,122 @@ +package in.koreatech.koin.domain.timetableV3.dto.response; + +import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.parseToStringList; +import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.calcWeek; +import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.parseToIntegerList; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import io.swagger.v3.oas.annotations.media.Schema; + +@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class) +public record ResponseLectureInfo( + @Schema(description = "요일 id", example = "0", requiredMode = REQUIRED) + Integer week, + + @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) + Integer startTime, + + @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) + Integer endTime, + + @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) + String place +) { + private static final String EMPTY_PLACE = ""; + + public static List getRegularLectureInfo(String classTime, String classPlace) { + List classTimes = parseToIntegerList(classTime); + List response = new ArrayList<>(); + + // 온라인 강의인 경우 + if (classTimes.isEmpty()) { + return response; + } + + List classPlaces = getClassPlaces(classPlace, classTimes); + + Integer prevTime = null; + Integer startTime = null; + Integer endTime = null; + int index = 0; + + for (Integer time : classTimes) { + if (Objects.isNull(prevTime) || time != prevTime + 1) { + if (!Objects.isNull(startTime)) { + addLectureInfo(response, startTime, endTime, classPlaces.get(index++)); + } + startTime = time; + } + + endTime = time; + prevTime = time; + } + + if (!Objects.isNull(startTime)) { + addLectureInfo(response, startTime, endTime, classPlaces.get(index)); + } + return response; + } + + // 정규 강의 장소 수정이 없을 경우 빈 장소를 주기 위한 리스트 반환 + private static List getClassPlaces(String classPlace, List classTimes) { + if (Objects.isNull(classPlace) || classPlace.isBlank()) { + return Collections.nCopies(classTimes.size(), EMPTY_PLACE); + } + return parseToStringList(classPlace); + } + + private static void addLectureInfo( + List response, Integer startTime, Integer endTime, String classPlace + ) { + response.add(new ResponseLectureInfo(calcWeek(startTime), startTime, endTime, classPlace)); + } + + public static List getCustomLectureInfo(String classTime, String classPlace) { + List classTimes = parseToIntegerList(classTime); + List response = new ArrayList<>(); + + List classPlaces = getClassPlaces(classPlace, classTimes); + + Integer prevTime = null; + Integer startTime = null; + Integer endTime = null; + int placesIndex = 0; + + for (int time : classTimes) { + if (Objects.isNull(prevTime)) { + startTime = time; + } + + if (!Objects.isNull(prevTime) && prevTime == -1) { + startTime = time; + prevTime = null; + endTime = null; + } + + if (time == -1) { + addLectureInfo(response, startTime, endTime, classPlaces.get(placesIndex++)); + } else if (!Objects.isNull(prevTime) && prevTime + 1 != time) { + addLectureInfo(response, startTime, endTime, classPlaces.get(placesIndex)); + startTime = time; + } + + endTime = time; + prevTime = time; + } + + if (!Objects.isNull(startTime) && prevTime != -1) { + addLectureInfo(response, startTime, endTime, classPlaces.get(placesIndex)); + } + + return response; + } +} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java index 6ee08dbba4..93c0df8b57 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java @@ -1,23 +1,17 @@ package in.koreatech.koin.domain.timetableV3.dto.response; import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; -import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.parseToStringList; -import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.calcWeek; -import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.parseToIntegerList; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; import com.fasterxml.jackson.databind.annotation.JsonNaming; import in.koreatech.koin.domain.timetable.model.Lecture; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; -import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import io.swagger.v3.oas.annotations.media.Schema; @JsonNaming(value = SnakeCaseStrategy.class) @@ -52,7 +46,7 @@ public record InnerTimetableLectureResponseV3( String designScore, @Schema(description = "강의 정보", requiredMode = NOT_REQUIRED) - List lectureInfos, + List lectureInfos, @Schema(description = "메모", example = "null", requiredMode = NOT_REQUIRED) String memo, @@ -75,77 +69,6 @@ public record InnerTimetableLectureResponseV3( @Schema(description = "학부", example = "디자인ㆍ건축공학부", requiredMode = NOT_REQUIRED) String department ) { - @JsonNaming(value = SnakeCaseStrategy.class) - public record LectureInfo( - @Schema(description = "요일 id", example = "0", requiredMode = REQUIRED) - Integer week, - - @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) - Integer startTime, - - @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) - Integer endTime, - - @Schema(description = "장소", example = "2공학관314", requiredMode = NOT_REQUIRED) - String place - ) { - private static final String EMPTY_PLACE = ""; - - public static List getCustomLectureInfo( - List timetableLectureInformations - ) { - return timetableLectureInformations.stream() - .map(timetableCustomLectureInformation -> new LectureInfo( - calcWeek(timetableCustomLectureInformation.getStartTime()), - timetableCustomLectureInformation.getStartTime(), - timetableCustomLectureInformation.getEndTime(), - getResponsePlace(timetableCustomLectureInformation.getPlace()) - )) - .collect(Collectors.toList()); - } - - public static List getRegularLectureInfo(String classTime, String classPlace) { - List classTimes = parseToIntegerList(classTime); - List classPlaces = parseToStringList(classPlace); - List response = new ArrayList<>(); - int index = 0; - - if (!classTimes.isEmpty()) { - Integer prevTime = null; - Integer startTime = null; - Integer endTime = null; - - for (Integer time : classTimes) { - if (Objects.isNull(prevTime) || time != prevTime + 1) { - addLectureInfo(response, startTime, endTime, classPlaces.get(index)); - startTime = time; - index++; - } - endTime = time; - prevTime = time; - } - - addLectureInfo(response, startTime, endTime, classPlaces.get(index)); - } - return response; - } - - private static void addLectureInfo( - List response, Integer startTime, Integer endTime, String classPlace - ) { - if (!Objects.isNull(startTime)) { - response.add(new LectureInfo(calcWeek(startTime), startTime, endTime, classPlace)); - } - } - - private static String getResponsePlace(String place) { - if (Objects.isNull(place)) { - return ""; - } - return place; - } - } - public static List from(List timetableLectures) { List InnerTimetableLectureResponses = new ArrayList<>(); @@ -160,7 +83,8 @@ public static List from(List null, null, null, - LectureInfo.getCustomLectureInfo(timetableLecture.getTimetableLectureInformations()), + ResponseLectureInfo.getCustomLectureInfo(timetableLecture.getClassTime(), + timetableLecture.getClassPlace()), timetableLecture.getMemo(), timetableLecture.getGrades(), timetableLecture.getClassTitle(), @@ -176,7 +100,8 @@ public static List from(List lecture.getRegularNumber(), lecture.getCode(), lecture.getDesignScore(), - LectureInfo.getRegularLectureInfo(lecture.getClassTime(), timetableLecture.getClassPlace()), + ResponseLectureInfo.getRegularLectureInfo(lecture.getClassTime(), + timetableLecture.getClassPlace()), timetableLecture.getMemo(), lecture.getGrades(), timetableLecture.getClassTitle() == null ? lecture.getName() : timetableLecture.getClassTitle(), diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java deleted file mode 100644 index 1a7ee45bde..0000000000 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/model/LectureInformation.java +++ /dev/null @@ -1,46 +0,0 @@ -package in.koreatech.koin.domain.timetableV3.model; - -import static jakarta.persistence.FetchType.LAZY; -import static jakarta.persistence.GenerationType.IDENTITY; -import static lombok.AccessLevel.PROTECTED; - -import in.koreatech.koin.domain.timetable.model.Lecture; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Getter -@Table(name = "lecture_information") -@NoArgsConstructor(access = PROTECTED) -public class LectureInformation { - - @Id - @GeneratedValue(strategy = IDENTITY) - private Integer id; - - // TODO. 시작시간과 끝시간 유효성 체크 로직 추가 - @Column(name = "start_time") - private Integer starTime; - - @Column(name = "end_time") - private Integer endTime; - - @ManyToOne(fetch = LAZY) - @JoinColumn(name = "lecture_id") - private Lecture lecture; - - @Builder - public LectureInformation(Integer starTime, Integer endTime, Lecture lecture) { - this.starTime = starTime; - this.endTime = endTime; - this.lecture = lecture; - } -} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java deleted file mode 100644 index 0d83b5c766..0000000000 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/model/TimetableLectureInformation.java +++ /dev/null @@ -1,70 +0,0 @@ -package in.koreatech.koin.domain.timetableV3.model; - -import static jakarta.persistence.FetchType.LAZY; -import static jakarta.persistence.GenerationType.IDENTITY; -import static lombok.AccessLevel.PROTECTED; - -import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Getter -@Table(name = "timetable_lecture_information") -@NoArgsConstructor(access = PROTECTED) -public class TimetableLectureInformation { - - @Id - @GeneratedValue(strategy = IDENTITY) - private Integer id; - - @Column(name = "start_time") - private Integer startTime; - - @Column(name = "end_time") - private Integer endTime; - - @Column(name = "place", length = 255) - private String place; - - @ManyToOne(fetch = LAZY) - @JoinColumn(name = "lecture_information_id") - private LectureInformation lectureInformation; - - @ManyToOne(fetch = LAZY) - @JoinColumn(name = "timetable_lecture_id") - private TimetableLecture timetableLecture; - - @Builder - private TimetableLectureInformation( - Integer id, - Integer startTime, - Integer endTime, - String place, - LectureInformation lectureInformation, - TimetableLecture timetableLecture - ) { - this.id = id; - this.startTime = startTime; - this.endTime = endTime; - this.place = place; - this.lectureInformation = lectureInformation; - this.timetableLecture = timetableLecture; - } - - public void setTimetableLectureId(TimetableLecture timetableLecture) { - this.timetableLecture = timetableLecture; - } - - public void setLectureInformationId(LectureInformation lectureInformation) { - this.lectureInformation = lectureInformation; - } -} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureInformationRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureInformationRepositoryV3.java deleted file mode 100644 index 6b38020d3c..0000000000 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureInformationRepositoryV3.java +++ /dev/null @@ -1,11 +0,0 @@ -package in.koreatech.koin.domain.timetableV3.repository; - -import java.util.List; - -import org.springframework.data.repository.Repository; - -import in.koreatech.koin.domain.timetableV3.model.LectureInformation; - -public interface LectureInformationRepositoryV3 extends Repository { - List findByLectureId(Integer lectureId); -} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index fe3fb6c373..f2c909032f 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -5,9 +5,6 @@ import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.joinClassPlaces; import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.joinClassTimes; -import static in.koreatech.koin.domain.timetableV3.validation.TimetableLectureValidate.checkDuplicateTimetableLectureTime; - -import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -17,7 +14,6 @@ import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureCreateRequest; import in.koreatech.koin.domain.timetableV3.dto.request.TimetableCustomLectureUpdateRequest; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; -import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index dd557e016c..1e2aafcdf5 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -47,13 +47,11 @@ public TimetableLectureResponseV3 updateTimetablesRegularLecture( TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); validateUserAuthorization(frame.getUser().getId(), userId); - TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); - if (!timetableLecture.getLecture().getName().equals(request.timetableLecture().classTitle())) { - timetableLecture.regularLectureTitleUpdate(request.timetableLecture().classTitle()); - } - - String classPlace = parseToString(request.timetableLecture().classPlaces()); - timetableLecture.regularLectureClassPlaceUpdate(classPlace); + TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id());; + timetableLecture.regularLectureUpdate( + request.timetableLecture().classTitle(), + parseToString(request.timetableLecture().classPlaces()) + ); timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java index 18cd74407a..3024fc9491 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.stream.Stream; -import in.koreatech.koin.domain.timetableV3.dto.request.LectureInfo; +import in.koreatech.koin.domain.timetableV3.dto.request.RequestLectureInfo; import lombok.NoArgsConstructor; @NoArgsConstructor(access = PRIVATE) @@ -17,26 +17,28 @@ public class ClassPlaceUtils { public static List parseToStringList(String classPlace) { return Stream.of(classPlace.split(",")) .map(String::strip) - .filter(place -> !place.isEmpty()) .toList(); } + // 정규 강의 장소 조인 public static String parseToString(List classPlaces) { StringBuilder classPlaceSegment = new StringBuilder(); for (int index = 0; index < classPlaces.size(); index++) { if (index > 0) { - classPlaceSegment.append(", "); + classPlaceSegment.append(CLASSPLACE_SEPARATOR); } classPlaceSegment.append(classPlaces.get(index).classPlace()); } return classPlaceSegment.toString(); } - public static String joinClassPlaces(List lectureInfos) { + // 커스텀 강의 장소 조인 + public static String joinClassPlaces(List lectureInfos) { StringBuilder classPlaces = new StringBuilder(); - for (int index = 0; index < lectureInfos.size(); index++) { - if (index > 0) classPlaces.append(CLASSPLACE_SEPARATOR); + if (index > 0) { + classPlaces.append(CLASSPLACE_SEPARATOR); + } classPlaces.append(lectureInfos.get(index).place()); } return classPlaces.toString(); diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java index 4388f1be61..0b2e427aae 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.stream.Stream; -import in.koreatech.koin.domain.timetableV3.dto.request.LectureInfo; +import in.koreatech.koin.domain.timetableV3.dto.request.RequestLectureInfo; import lombok.NoArgsConstructor; @NoArgsConstructor(access = PRIVATE) @@ -15,6 +15,7 @@ public class ClassTimeUtils { private static final Integer DIVIDE_TIME_UNIT = 100; private static final Integer CLASSTIME_SEPARATOR = -1; + // 정규 강의 시간 리스트로 변환 public static List parseToIntegerList(String classTime) { return Stream.of(classTime.replaceAll("[\\[\\]]", "").split(",")) .map(String::strip) @@ -23,6 +24,7 @@ public static List parseToIntegerList(String classTime) { .toList(); } + // week 계산 public static Integer calcWeek(Integer startTime) { if (startTime != 0) { return startTime / DIVIDE_TIME_UNIT; @@ -30,7 +32,8 @@ public static Integer calcWeek(Integer startTime) { return 0; } - public static String joinClassTimes(List lectureInfos) { + // 커스텀 강의 시간 조인 + public static String joinClassTimes(List lectureInfos) { List classTimes = new ArrayList<>(); for (int index = 0; index < lectureInfos.size(); index++) { @@ -39,7 +42,7 @@ public static String joinClassTimes(List lectureInfos) { int startTime = lectureInfos.get(index).startTime(); int endTime = lectureInfos.get(index).endTime(); - while (startTime > endTime) { + while (startTime <= endTime) { classTimes.add(startTime++); } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/validation/TimetableLectureValidate.java b/src/main/java/in/koreatech/koin/domain/timetableV3/validation/TimetableLectureValidate.java deleted file mode 100644 index fb4dfd9d98..0000000000 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/validation/TimetableLectureValidate.java +++ /dev/null @@ -1,68 +0,0 @@ -package in.koreatech.koin.domain.timetableV3.validation; - -import static lombok.AccessLevel.PRIVATE; - -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; - -import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; -import in.koreatech.koin.domain.timetableV3.exception.TimetableLectureTimeDuplicateException; -import in.koreatech.koin.domain.timetableV3.model.TimetableLectureInformation; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = PRIVATE) -public class TimetableLectureValidate { - - public static void checkDuplicateTimetableLectureTime( - List timetableLectures, List timetableLectureInformations - ) { - Queue classInformations = getClassInformations(timetableLectures); - - for (ClassInformation classInformation : classInformations) { - for (TimetableLectureInformation timetableLectureInformation : timetableLectureInformations) { - int startTime = timetableLectureInformation.getLectureInformation() != null ? - timetableLectureInformation.getLectureInformation().getStarTime() : - timetableLectureInformation.getStartTime(); - int endTime = timetableLectureInformation.getLectureInformation() != null ? - timetableLectureInformation.getLectureInformation().getEndTime() : - timetableLectureInformation.getEndTime(); - - if (classInformation.checkBetweenTime(startTime, endTime)) { - throw new TimetableLectureTimeDuplicateException( - String.format("%s 강의 시간과 중복됩니다", classInformation.classTitle)); - } - } - } - } - - private static Queue getClassInformations(List timetableLectures) { - Queue classInformations = new LinkedList<>(); - - for (TimetableLecture timetableLecture : timetableLectures) { - List timetableLectureInformations = timetableLecture.getTimetableLectureInformations(); - - for (TimetableLectureInformation timetableLectureInformation : timetableLectureInformations) { - int startTime = timetableLectureInformation.getLectureInformation() != null ? - timetableLectureInformation.getLectureInformation().getStarTime() : - timetableLectureInformation.getStartTime(); - int endTime = timetableLectureInformation.getLectureInformation() != null ? - timetableLectureInformation.getLectureInformation().getEndTime() : - timetableLectureInformation.getEndTime(); - - classInformations.add(new ClassInformation(timetableLecture.getClassTitle(), startTime, endTime)); - } - } - return classInformations; - } - - public record ClassInformation( - String classTitle, - int startTime, - int endTime - ) { - public boolean checkBetweenTime(int startTime, int endTime) { - return this.startTime <= startTime || this.endTime <= endTime; - } - } -} From ac8a79263d28353a7a6208dd39e740fbbbceed49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 3 Jan 2025 19:38:03 +0900 Subject: [PATCH 38/61] =?UTF-8?q?chore:=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...estLectureInfo.java => LectureInfoRequest.java} | 2 +- .../TimetableCustomLectureCreateRequest.java | 2 +- .../TimetableCustomLectureUpdateRequest.java | 2 +- ...seLectureInfo.java => LectureInfoResponse.java} | 14 +++++++------- .../dto/response/TimetableLectureResponseV3.java | 6 +++--- .../domain/timetableV3/utils/ClassPlaceUtils.java | 4 ++-- .../domain/timetableV3/utils/ClassTimeUtils.java | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) rename src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/{RequestLectureInfo.java => LectureInfoRequest.java} (96%) rename src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/{ResponseLectureInfo.java => LectureInfoResponse.java} (90%) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/RequestLectureInfo.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/LectureInfoRequest.java similarity index 96% rename from src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/RequestLectureInfo.java rename to src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/LectureInfoRequest.java index f300433ccd..a433532cd2 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/RequestLectureInfo.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/LectureInfoRequest.java @@ -10,7 +10,7 @@ import jakarta.validation.constraints.Size; @JsonNaming(value = SnakeCaseStrategy.class) -public record RequestLectureInfo( +public record LectureInfoRequest( @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) Integer startTime, diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java index b3701f6878..e224447561 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java @@ -36,7 +36,7 @@ public record InnerTimeTableCustomLectureRequest( @Valid @Schema(description = "커스텀 강의 시간 정보", requiredMode = REQUIRED) - List lectureInfos, + List lectureInfos, @Schema(description = "교수명", example = "교수명", requiredMode = NOT_REQUIRED) @Size(max = 30, message = "교수명의 최대 글자는 30글자 입니다.") diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java index 08aef517d6..acb08dd1ba 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java @@ -36,7 +36,7 @@ public record InnerTimeTableCustomLectureRequest( @Valid @Schema(description = "커스텀 강의 시간 정보", requiredMode = REQUIRED) - List lectureInfos, + List lectureInfos, @Schema(description = "교수명", example = "교수명", requiredMode = NOT_REQUIRED) @Size(max = 30, message = "교수명의 최대 글자는 30글자 입니다.") diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/ResponseLectureInfo.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java similarity index 90% rename from src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/ResponseLectureInfo.java rename to src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java index 14b77b0cdf..e380e31a31 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/ResponseLectureInfo.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java @@ -17,7 +17,7 @@ import io.swagger.v3.oas.annotations.media.Schema; @JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class) -public record ResponseLectureInfo( +public record LectureInfoResponse( @Schema(description = "요일 id", example = "0", requiredMode = REQUIRED) Integer week, @@ -32,9 +32,9 @@ public record ResponseLectureInfo( ) { private static final String EMPTY_PLACE = ""; - public static List getRegularLectureInfo(String classTime, String classPlace) { + public static List getRegularLectureInfo(String classTime, String classPlace) { List classTimes = parseToIntegerList(classTime); - List response = new ArrayList<>(); + List response = new ArrayList<>(); // 온라인 강의인 경우 if (classTimes.isEmpty()) { @@ -75,14 +75,14 @@ private static List getClassPlaces(String classPlace, List clas } private static void addLectureInfo( - List response, Integer startTime, Integer endTime, String classPlace + List response, Integer startTime, Integer endTime, String classPlace ) { - response.add(new ResponseLectureInfo(calcWeek(startTime), startTime, endTime, classPlace)); + response.add(new LectureInfoResponse(calcWeek(startTime), startTime, endTime, classPlace)); } - public static List getCustomLectureInfo(String classTime, String classPlace) { + public static List getCustomLectureInfo(String classTime, String classPlace) { List classTimes = parseToIntegerList(classTime); - List response = new ArrayList<>(); + List response = new ArrayList<>(); List classPlaces = getClassPlaces(classPlace, classTimes); diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java index 93c0df8b57..4313d92175 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/TimetableLectureResponseV3.java @@ -46,7 +46,7 @@ public record InnerTimetableLectureResponseV3( String designScore, @Schema(description = "강의 정보", requiredMode = NOT_REQUIRED) - List lectureInfos, + List lectureInfos, @Schema(description = "메모", example = "null", requiredMode = NOT_REQUIRED) String memo, @@ -83,7 +83,7 @@ public static List from(List null, null, null, - ResponseLectureInfo.getCustomLectureInfo(timetableLecture.getClassTime(), + LectureInfoResponse.getCustomLectureInfo(timetableLecture.getClassTime(), timetableLecture.getClassPlace()), timetableLecture.getMemo(), timetableLecture.getGrades(), @@ -100,7 +100,7 @@ public static List from(List lecture.getRegularNumber(), lecture.getCode(), lecture.getDesignScore(), - ResponseLectureInfo.getRegularLectureInfo(lecture.getClassTime(), + LectureInfoResponse.getRegularLectureInfo(lecture.getClassTime(), timetableLecture.getClassPlace()), timetableLecture.getMemo(), lecture.getGrades(), diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java index 3024fc9491..daa7247799 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.stream.Stream; -import in.koreatech.koin.domain.timetableV3.dto.request.RequestLectureInfo; +import in.koreatech.koin.domain.timetableV3.dto.request.LectureInfoRequest; import lombok.NoArgsConstructor; @NoArgsConstructor(access = PRIVATE) @@ -33,7 +33,7 @@ public static String parseToString(List classPlaces) { } // 커스텀 강의 장소 조인 - public static String joinClassPlaces(List lectureInfos) { + public static String joinClassPlaces(List lectureInfos) { StringBuilder classPlaces = new StringBuilder(); for (int index = 0; index < lectureInfos.size(); index++) { if (index > 0) { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java index 0b2e427aae..d433c327ee 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.stream.Stream; -import in.koreatech.koin.domain.timetableV3.dto.request.RequestLectureInfo; +import in.koreatech.koin.domain.timetableV3.dto.request.LectureInfoRequest; import lombok.NoArgsConstructor; @NoArgsConstructor(access = PRIVATE) @@ -33,7 +33,7 @@ public static Integer calcWeek(Integer startTime) { } // 커스텀 강의 시간 조인 - public static String joinClassTimes(List lectureInfos) { + public static String joinClassTimes(List lectureInfos) { List classTimes = new ArrayList<>(); for (int index = 0; index < lectureInfos.size(); index++) { From cff3f1c5684fc7ec356134f5ce0653e90bdaddab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 3 Jan 2025 19:39:56 +0900 Subject: [PATCH 39/61] =?UTF-8?q?chore:=20=EC=BD=94=EB=93=9C=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/LectureInfoResponse.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java index e380e31a31..7e658c34ad 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java @@ -66,20 +66,6 @@ public static List getRegularLectureInfo(String classTime, return response; } - // 정규 강의 장소 수정이 없을 경우 빈 장소를 주기 위한 리스트 반환 - private static List getClassPlaces(String classPlace, List classTimes) { - if (Objects.isNull(classPlace) || classPlace.isBlank()) { - return Collections.nCopies(classTimes.size(), EMPTY_PLACE); - } - return parseToStringList(classPlace); - } - - private static void addLectureInfo( - List response, Integer startTime, Integer endTime, String classPlace - ) { - response.add(new LectureInfoResponse(calcWeek(startTime), startTime, endTime, classPlace)); - } - public static List getCustomLectureInfo(String classTime, String classPlace) { List classTimes = parseToIntegerList(classTime); List response = new ArrayList<>(); @@ -119,4 +105,18 @@ public static List getCustomLectureInfo(String classTime, S return response; } + + // 정규 강의 장소 수정이 없을 경우 빈 장소를 주기 위한 리스트 반환 + private static List getClassPlaces(String classPlace, List classTimes) { + if (Objects.isNull(classPlace) || classPlace.isBlank()) { + return Collections.nCopies(classTimes.size(), EMPTY_PLACE); + } + return parseToStringList(classPlace); + } + + private static void addLectureInfo( + List response, Integer startTime, Integer endTime, String classPlace + ) { + response.add(new LectureInfoResponse(calcWeek(startTime), startTime, endTime, classPlace)); + } } From 32600f0cf0d0b7eff648b1a81f491ba00ca73281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 3 Jan 2025 20:27:16 +0900 Subject: [PATCH 40/61] =?UTF-8?q?feat:=20=EB=A1=A4=EB=B0=B1=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV3/controller/LectureApiV3.java | 2 +- .../controller/TimetableLectureApiV3.java | 39 ++++++++++++++++ .../TimetableLectureControllerV3.java | 21 +++++++++ ...imetableLectureTimeDuplicateException.java | 19 -------- .../TimetableFrameRepositoryV3.java | 15 ++++++ .../TimetableLectureRepositoryV3.java | 14 ++++++ .../service/TimetableLectureServiceV3.java | 46 +++++++++++++++++++ 7 files changed, 136 insertions(+), 20 deletions(-) delete mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/exception/TimetableLectureTimeDuplicateException.java diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java index ca67934343..d68dd7eeb2 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java @@ -25,7 +25,7 @@ public interface LectureApiV3 { } ) @Operation(summary = "정규 강의 목록 조회") - @GetMapping("/lectures") + @GetMapping("/v3/lectures") ResponseEntity> getLectures( String semesterDate ); diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java index 54b498885f..e054afbafa 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java @@ -2,8 +2,11 @@ import static in.koreatech.koin.domain.user.model.UserType.STUDENT; +import java.util.List; + import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; @@ -34,4 +37,40 @@ ResponseEntity getTimetableLecture( @RequestParam(value = "timetable_frame_id") Integer timetableFrameId, @Auth(permit = {STUDENT}) Integer userId ); + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) + } + ) + @Operation(summary = "삭제한 시간표 강의 복구") + @SecurityRequirement(name = "Jwt Authentication") + @PostMapping("/v3/timetables/lecture/rollback") + ResponseEntity rollbackTimetableLecture( + @RequestParam(name = "timetable_lectures_id") List timetableLecturesId, + @Auth(permit = {STUDENT}) Integer userId + ); + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) + } + ) + @Operation(summary = "삭제한 시간표 프레임과 강의 복구", + description = """ + 1. 삭제된 시간표 프레임: 삭제된 시간표 프레임과 그에 속한 강의 정보를 복구합니다. \n + 2. 삭제되지 않은 시간표 프레임: 시간표 프레임에 속한 강의 정보를 복구합니다. + """) + @SecurityRequirement(name = "Jwt Authentication") + @PostMapping("/v3/timetables/frame/rollback") + ResponseEntity rollbackTimetableFrame( + @RequestParam(name = "timetable_frame_id") Integer timetableFrameId, + @Auth(permit = {STUDENT}) Integer userId + ); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java index 83d0a0ec6c..7ec8abff03 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java @@ -2,8 +2,11 @@ import static in.koreatech.koin.domain.user.model.UserType.STUDENT; +import java.util.List; + import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -26,4 +29,22 @@ public ResponseEntity getTimetableLecture( TimetableLectureResponseV3 response = lectureServiceV3.getTimetableLecture(timetableFrameId, userId); return ResponseEntity.ok(response); } + + @PostMapping("/v3/timetables/lecture/rollback") + public ResponseEntity rollbackTimetableLecture( + @RequestParam(name = "timetable_lectures_id") List timetableLecturesId, + @Auth(permit = {STUDENT}) Integer userId + ) { + TimetableLectureResponseV3 response = lectureServiceV3.rollbackTimetableLecture(timetableLecturesId, userId); + return ResponseEntity.ok(response); + } + + @PostMapping("/v3/timetables/frame/rollback") + public ResponseEntity rollbackTimetableFrame( + @RequestParam(name = "timetable_frame_id") Integer timetableFrameId, + @Auth(permit = {STUDENT}) Integer userId + ) { + TimetableLectureResponseV3 response = lectureServiceV3.rollbackTimetableFrame(timetableFrameId, userId); + return ResponseEntity.ok(response); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/exception/TimetableLectureTimeDuplicateException.java b/src/main/java/in/koreatech/koin/domain/timetableV3/exception/TimetableLectureTimeDuplicateException.java deleted file mode 100644 index 973240d0e1..0000000000 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/exception/TimetableLectureTimeDuplicateException.java +++ /dev/null @@ -1,19 +0,0 @@ -package in.koreatech.koin.domain.timetableV3.exception; - -import in.koreatech.koin.global.exception.KoinIllegalArgumentException; - -public class TimetableLectureTimeDuplicateException extends KoinIllegalArgumentException { - public static final String DEFAULT_MESSAGE = "강의 시간이 겹칩니다."; - - public TimetableLectureTimeDuplicateException(String message) { - super(message); - } - - public TimetableLectureTimeDuplicateException(String message, String detail) { - super(message, detail); - } - - public static TimetableLectureTimeDuplicateException withDetail(String detail) { - return new TimetableLectureTimeDuplicateException(DEFAULT_MESSAGE, detail); - } -} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableFrameRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableFrameRepositoryV3.java index 65350b97d9..7f8cef0282 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableFrameRepositoryV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableFrameRepositoryV3.java @@ -3,10 +3,15 @@ import java.util.List; import java.util.Optional; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; +import org.springframework.data.repository.query.Param; import in.koreatech.koin.domain.timetable.exception.TimetableNotFoundException; +import in.koreatech.koin.domain.timetable.model.Semester; +import in.koreatech.koin.domain.timetableV2.exception.TimetableFrameNotFoundException; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; +import in.koreatech.koin.domain.user.model.User; public interface TimetableFrameRepositoryV3 extends Repository { @@ -18,4 +23,14 @@ default TimetableFrame getById(Integer id) { } List findByUserIdAndIsMainTrue(Integer userId); + + @Query(value = "SELECT * FROM timetable_frame WHERE id = :id", nativeQuery = true) + Optional findByIdWithDeleted(@Param("id") Integer id); + + default TimetableFrame getByIdWithDeleted(Integer id) { + return findByIdWithDeleted(id) + .orElseThrow(() -> TimetableFrameNotFoundException.withDetail("id: " + id)); + } + + boolean existsByUserAndSemester(User user, Semester semester); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java index 7ec0b2892b..0f91a8a174 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/TimetableLectureRepositoryV3.java @@ -1,8 +1,11 @@ package in.koreatech.koin.domain.timetableV3.repository; +import java.util.List; import java.util.Optional; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; +import org.springframework.data.repository.query.Param; import in.koreatech.koin.domain.timetableV2.exception.TimetableLectureNotFoundException; import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; @@ -16,4 +19,15 @@ default TimetableLecture getById(Integer id) { return findById(id) .orElseThrow(() -> TimetableLectureNotFoundException.withDetail("id: " + id)); } + + @Query(value = "SELECT * FROM timetable_lecture WHERE id = :id", nativeQuery = true) + Optional findByIdWithDeleted(@Param("id") Integer id); + + default TimetableLecture getByIdWithDeleted(Integer id) { + return findByIdWithDeleted(id) + .orElseThrow(() -> TimetableLectureNotFoundException.withDetail("id: " + id)); + } + + @Query(value = "SELECT * FROM timetable_lecture WHERE frame_id = :frameId", nativeQuery = true) + List findAllByFrameIdWithDeleted(@Param("frameId") Integer frameId); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java index 85b2fd523f..63323a2639 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java @@ -4,18 +4,31 @@ import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; +import java.util.List; + import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; +import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; +import in.koreatech.koin.domain.user.model.User; +import in.koreatech.koin.domain.user.repository.UserRepository; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; import lombok.RequiredArgsConstructor; @Service @RequiredArgsConstructor public class TimetableLectureServiceV3 { + @PersistenceContext + private EntityManager entityManager; private final TimetableFrameRepositoryV3 timetableFrameRepositoryV3; + private final TimetableLectureRepositoryV3 timetableLectureRepositoryV3; + private final UserRepository userRepository; public TimetableLectureResponseV3 getTimetableLecture(Integer timetableFrameId, Integer userId) { TimetableFrame frame = timetableFrameRepositoryV3.getById(timetableFrameId); @@ -28,4 +41,37 @@ private TimetableLectureResponseV3 getTimetableLectureResponse(Integer userId, T int totalGrades = calculateTotalGrades(timetableFrameRepositoryV3.findByUserIdAndIsMainTrue(userId)); return TimetableLectureResponseV3.of(timetableFrame, grades, totalGrades); } + + @Transactional + public TimetableLectureResponseV3 rollbackTimetableLecture(List timetableLecturesId, Integer userId) { + timetableLecturesId.stream() + .map(timetableLectureRepositoryV3::getByIdWithDeleted) + .peek(lecture -> validateUserAuthorization(lecture.getTimetableFrame().getUser().getId(), userId)) + .forEach(TimetableLecture::undelete); + entityManager.flush(); + TimetableLecture timeTableLecture = timetableLectureRepositoryV3.getById(timetableLecturesId.get(0)); + return getTimetableLectureResponse(userId, timeTableLecture.getTimetableFrame()); + } + + @Transactional + public TimetableLectureResponseV3 rollbackTimetableFrame(Integer frameId, Integer userId) { + TimetableFrame timetableFrame = timetableFrameRepositoryV3.getByIdWithDeleted(frameId); + validateUserAuthorization(timetableFrame.getUser().getId(), userId); + + User user = userRepository.getById(userId); + boolean hasTimetableFrame = timetableFrameRepositoryV3.existsByUserAndSemester(user, + timetableFrame.getSemester()); + + if (!hasTimetableFrame) { + timetableFrame.updateMainFlag(true); + } + timetableFrame.undelete(); + + timetableLectureRepositoryV3.findAllByFrameIdWithDeleted(timetableFrame.getId()).stream() + .map(TimetableLecture::getId) + .map(timetableLectureRepositoryV3::getByIdWithDeleted) + .forEach(TimetableLecture::undelete); + entityManager.flush(); + return getTimetableLectureResponse(userId, timetableFrame); + } } From bd984064a04306608926385d34c48f3e06f478e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Fri, 3 Jan 2025 20:30:22 +0900 Subject: [PATCH 41/61] =?UTF-8?q?chore:=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20im?= =?UTF-8?q?port=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/timetableV3/service/LectureServiceV3.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java index c756e425b4..285f571f21 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java @@ -4,7 +4,6 @@ import org.springframework.stereotype.Service; -import in.koreatech.koin.domain.timetable.model.Lecture; import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; import lombok.RequiredArgsConstructor; From f577b73237cd259d83e519848f2a22054507346e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 4 Jan 2025 00:19:16 +0900 Subject: [PATCH 42/61] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/acceptance/LectureApiTest.java | 72 ++++++++ .../acceptance/TimetableLectureV3ApiTest.java | 166 ++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java create mode 100644 src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java diff --git a/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java b/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java new file mode 100644 index 0000000000..071f55116b --- /dev/null +++ b/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java @@ -0,0 +1,72 @@ +package in.koreatech.koin.acceptance; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.transaction.annotation.Transactional; + +import in.koreatech.koin.AcceptanceTest; +import in.koreatech.koin.fixture.LectureFixture; + +@SuppressWarnings("NonAsciiCharacters") +@Transactional +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class LectureApiTest extends AcceptanceTest { + + @Autowired + private LectureFixture lectureFixture; + + @BeforeAll + void setup() { + clear(); + } + + @Test + void 특정_학기_강의를_조회한다() throws Exception { + String semester = "20201"; + lectureFixture.HRD_개론(semester); + + mockMvc.perform( + get("/v3/lectures") + .param("semester_date", semester) + .contentType(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk()) + .andExpect(content().json(""" + [ + { + "id" : 1, + "code": "BSM590", + "name": "컴퓨팅사고", + "grades": "3", + "lecture_class": "06", + "regular_number": "22", + "department": "기계공학부", + "target": "기공1", + "professor": "박한수,최준호", + "is_english": "", + "design_score": "0", + "is_elearning": "", + "lecture_infos": [ + { + "week": 0, + "start_time": 12, + "end_time": 15 + }, + { + "week": 2, + "start_time": 210, + "end_time": 213 + } + ] + } + ] + """)); + } +} diff --git a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java new file mode 100644 index 0000000000..6be5c552b9 --- /dev/null +++ b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java @@ -0,0 +1,166 @@ +package in.koreatech.koin.acceptance; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.transaction.annotation.Transactional; + +import in.koreatech.koin.AcceptanceTest; +import in.koreatech.koin.domain.timetable.model.Semester; +import in.koreatech.koin.domain.user.model.User; +import in.koreatech.koin.fixture.LectureFixture; +import in.koreatech.koin.fixture.SemesterFixture; +import in.koreatech.koin.fixture.TimeTableV2Fixture; +import in.koreatech.koin.fixture.UserFixture; + +@SuppressWarnings("NonAsciiCharacters") +@Transactional +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class TimetableLectureV3ApiTest extends AcceptanceTest { + + @Autowired + private TimeTableV2Fixture timetableV2Fixture; + + @Autowired + private UserFixture userFixture; + + @Autowired + private SemesterFixture semesterFixture; + + @Autowired + private LectureFixture lectureFixture; + + private User user; + private String token; + private Semester semester; + + @BeforeAll + void setup() { + clear(); + user = userFixture.준호_학생().getUser(); + token = userFixture.getToken(user); + semester = semesterFixture.semester("20192"); + } + + @Test + void 정규강의를_생성한다() throws Exception { + timetableV2Fixture.시간표1(user, semester); + lectureFixture.HRD_개론(semester.getSemester()); + + mockMvc.perform( + post("/v3/timetables/lecture/regular") + .header("Authorization", "Bearer " + token) + .content(""" + { + "timetable_frame_id" : 1, + "lecture_id" : 1 + } + """) + .contentType(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk()) + .andExpect(content().json(""" + { + "timetable_frame_id": 1, + "timetable": [ + { + "id": 1, + "lecture_id" : 1, + "regular_number": "22", + "code": "BSM590", + "design_score": "0", + "lecture_infos": [ + { + "week": 0, + "start_time": 12, + "end_time": 15 + }, + { + "week": 2, + "start_time": 210, + "end_time": 213, + "place": "" + } + ], + "memo": null, + "grades": "3", + "class_title": "컴퓨팅사고", + "lecture_class": "06", + "target": "기공1", + "professor": "박한수,최준호", + "department": "기계공학부" + } + ], + "grades": 3, + "total_grades": 3 + } + """)); + } + + @Test + void 커스텀강의를_생성한다() throws Exception { + timetableV2Fixture.시간표1(user, semester); + + mockMvc.perform( + post("/v3/timetables/lecture/custom") + .header("Authorization", "Bearer " + token) + .content(""" + { + "timetable_frame_id": 1, + "timetable_lecture": { + "class_title": "커스텀 강의 이름", + "lecture_infos": [ + { + "start_time": 112, + "end_time": 115, + "place": "2공학관314" + } + ], + "professor": "교수명", + "grades": "3", + "memo": "메모" + } + } + """) + .contentType(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk()) + .andExpect(content().json(""" + { + "timetable_frame_id": 1, + "timetable": [ + { + "id": 1, + "lecture_id" : null, + "regular_number": null, + "code": null, + "design_score": null, + "lecture_infos": [ + { + "week": 1, + "start_time": 112, + "end_time": 115, + "place": "2공학관314" + } + ], + "memo": "메모", + "grades": "3", + "class_title": "커스텀 강의 이름", + "lecture_class": null, + "target": null, + "professor": "교수명", + "department": null + } + ], + "grades": 3, + "total_grades": 3 + } + """)); + } +} From bdda0b329560e64d314688ba4c939dbcfff77234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 4 Jan 2025 00:24:41 +0900 Subject: [PATCH 43/61] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/TimetableLectureV3ApiTest.java | 160 +++++++++++++++++- 1 file changed, 159 insertions(+), 1 deletion(-) diff --git a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java index 6be5c552b9..5bf2686dd3 100644 --- a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java @@ -4,6 +4,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.List; +import java.util.stream.Collectors; + import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; @@ -12,7 +15,10 @@ import org.springframework.transaction.annotation.Transactional; import in.koreatech.koin.AcceptanceTest; +import in.koreatech.koin.domain.timetable.model.Lecture; import in.koreatech.koin.domain.timetable.model.Semester; +import in.koreatech.koin.domain.timetableV2.model.TimetableFrame; +import in.koreatech.koin.domain.timetableV2.model.TimetableLecture; import in.koreatech.koin.domain.user.model.User; import in.koreatech.koin.fixture.LectureFixture; import in.koreatech.koin.fixture.SemesterFixture; @@ -137,7 +143,7 @@ void setup() { "timetable": [ { "id": 1, - "lecture_id" : null, + "lecture_id": null, "regular_number": null, "code": null, "design_score": null, @@ -163,4 +169,156 @@ void setup() { } """)); } + + @Test + void 시간표에서_삭제된_강의를_복구한다_V3() throws Exception { + Lecture 건축구조의_이해_및_실습 = lectureFixture.건축구조의_이해_및_실습(semester.getSemester()); + Lecture HRD_개론 = lectureFixture.HRD_개론(semester.getSemester()); + TimetableFrame frame = timetableV2Fixture.시간표8(user, semester, 건축구조의_이해_및_실습, HRD_개론); + + List timetableLecturesId = frame.getTimetableLectures().stream() + .map(TimetableLecture::getId) + .toList(); + + mockMvc.perform( + post("/v3/timetables/lecture/rollback") + .header("Authorization", "Bearer " + token) + .param("timetable_lectures_id", timetableLecturesId.stream() + .map(String::valueOf) + .collect(Collectors.joining(","))) + .contentType(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk()) + .andExpect(content().json(""" + { + "timetable_frame_id": 1, + "timetable": [ + { + "id" : 1, + "lecture_id" : 1, + "regular_number": "25", + "code": "ARB244", + "design_score": "0", + "lecture_infos": [ + { + "week": 2, + "start_time": 200, + "end_time": 207, + "place": "" + } + ], + "memo": null, + "grades": "3", + "class_title": "건축구조의 이해 및 실습", + "lecture_class": "01", + "target": "디자 1 건축", + "professor": "황현식", + "department": "디자인ㆍ건축공학부" + }, + { + "id": 2, + "lecture_id": 2, + "regular_number": "22", + "code": "BSM590", + "design_score": "0", + "lecture_infos": [ + { + "week": 0, + "start_time": 12, + "end_time": 15 + }, + { + "week": 2, + "start_time": 210, + "end_time": 213, + "place": "" + } + ], + "memo": null, + "grades": "3", + "class_title": "컴퓨팅사고", + "lecture_class": "06", + "target": "기공1", + "professor": "박한수,최준호", + "department": "기계공학부" + } + ], + "grades": 6, + "total_grades": 6 + } + """)); + } + + @Test + void 삭제된_시간표프레임과_그에_해당하는_강의를_복구한다_V3() throws Exception { + Lecture 건축구조의_이해_및_실습 = lectureFixture.건축구조의_이해_및_실습(semester.getSemester()); + Lecture HRD_개론 = lectureFixture.HRD_개론(semester.getSemester()); + TimetableFrame frame = timetableV2Fixture.시간표7(user, semester, 건축구조의_이해_및_실습, HRD_개론); + + mockMvc.perform( + post("/v3/timetables/frame/rollback") + .header("Authorization", "Bearer " + token) + .param("timetable_frame_id", String.valueOf(frame.getId())) + .contentType(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk()) + .andExpect(content().json(""" + { + "timetable_frame_id": 1, + "timetable": [ + { + "id" : 1, + "lecture_id" : 1, + "regular_number": "25", + "code": "ARB244", + "design_score": "0", + "lecture_infos": [ + { + "week": 2, + "start_time": 200, + "end_time": 207, + "place": "" + } + ], + "memo": null, + "grades": "3", + "class_title": "건축구조의 이해 및 실습", + "lecture_class": "01", + "target": "디자 1 건축", + "professor": "황현식", + "department": "디자인ㆍ건축공학부" + }, + { + "id": 2, + "lecture_id": 2, + "regular_number": "22", + "code": "BSM590", + "design_score": "0", + "lecture_infos": [ + { + "week": 0, + "start_time": 12, + "end_time": 15 + }, + { + "week": 2, + "start_time": 210, + "end_time": 213, + "place": "" + } + ], + "memo": null, + "grades": "3", + "class_title": "컴퓨팅사고", + "lecture_class": "06", + "target": "기공1", + "professor": "박한수,최준호", + "department": "기계공학부" + } + ], + "grades": 6, + "total_grades": 6 + } + """)); + } } From 55c9b4874d6c2091079b6c3e062cc1a594d7716c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 4 Jan 2025 00:48:42 +0900 Subject: [PATCH 44/61] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/LectureInfoResponse.java | 7 ++++--- .../timetableV3/dto/response/LectureResponseV3.java | 12 ++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java index 7e658c34ad..418feef106 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java @@ -32,6 +32,7 @@ public record LectureInfoResponse( ) { private static final String EMPTY_PLACE = ""; + // 역정규화 된 정유 강의 정보 정규화 하는 메소드 public static List getRegularLectureInfo(String classTime, String classPlace) { List classTimes = parseToIntegerList(classTime); List response = new ArrayList<>(); @@ -55,7 +56,6 @@ public static List getRegularLectureInfo(String classTime, } startTime = time; } - endTime = time; prevTime = time; } @@ -66,6 +66,7 @@ public static List getRegularLectureInfo(String classTime, return response; } + // 역정규화 된 커스텀 강의 정부 정규화 하는 메소드 public static List getCustomLectureInfo(String classTime, String classPlace) { List classTimes = parseToIntegerList(classTime); List response = new ArrayList<>(); @@ -106,14 +107,14 @@ public static List getCustomLectureInfo(String classTime, S return response; } - // 정규 강의 장소 수정이 없을 경우 빈 장소를 주기 위한 리스트 반환 + // 강의 장소가 null 혹은 빈 값인 경우 강의 장소를 공백으로 넘기기 위한 메소드 private static List getClassPlaces(String classPlace, List classTimes) { if (Objects.isNull(classPlace) || classPlace.isBlank()) { return Collections.nCopies(classTimes.size(), EMPTY_PLACE); } return parseToStringList(classPlace); } - + private static void addLectureInfo( List response, Integer startTime, Integer endTime, String classPlace ) { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java index f4db9d4aae..252cd83669 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java @@ -68,6 +68,7 @@ public record LectureInfo( @Schema(description = "종료 시간", example = "115", requiredMode = REQUIRED) Integer endTime ) { + // 역정규화된 정규 강의 정보를 정규화 하는 메소드 public static List from(String classTime) { List classTimes = parseToIntegerList(classTime); List response = new ArrayList<>(); @@ -79,22 +80,25 @@ public static List from(String classTime) { for (Integer time : classTimes) { if (Objects.isNull(prevTime) || time != prevTime + 1) { - addLectureInfo(response, startTime, endTime); + if (!Objects.isNull(startTime)) { + addLectureInfo(response, startTime, endTime); + } startTime = time; } endTime = time; prevTime = time; } + if (!Objects.isNull(startTime)) { + addLectureInfo(response, startTime, endTime); + } addLectureInfo(response, startTime, endTime); } return response; } private static void addLectureInfo(List response, Integer startTime, Integer endTime) { - if (!Objects.isNull(startTime)) { - response.add(new LectureInfo(calcWeek(startTime), startTime, endTime)); - } + response.add(new LectureInfo(calcWeek(startTime), startTime, endTime)); } } From cdd6f649a230542f6561fd35eda5cd1d667e54c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 4 Jan 2025 00:48:52 +0900 Subject: [PATCH 45/61] =?UTF-8?q?chore:=20flyway=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...__create_timetable_lecture_information.sql | 10 --- ...V110__create_lecture_information_table.sql | 8 --- ...ray_class_time_normalization_procedure.sql | 53 -------------- ...ray_class_time_normalization_procedure.sql | 71 ------------------- 4 files changed, 142 deletions(-) delete mode 100644 src/main/resources/db/migration/V109__create_timetable_lecture_information.sql delete mode 100644 src/main/resources/db/migration/V110__create_lecture_information_table.sql delete mode 100644 src/main/resources/db/migration/V111__add_array_class_time_normalization_procedure.sql delete mode 100644 src/main/resources/db/migration/V112__add_call_array_class_time_normalization_procedure.sql diff --git a/src/main/resources/db/migration/V109__create_timetable_lecture_information.sql b/src/main/resources/db/migration/V109__create_timetable_lecture_information.sql deleted file mode 100644 index 4deb817e02..0000000000 --- a/src/main/resources/db/migration/V109__create_timetable_lecture_information.sql +++ /dev/null @@ -1,10 +0,0 @@ -CREATE TABLE IF NOT EXISTS `koin`.`timetable_lecture_information` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '고유 id', - `start_time` INT UNSIGNED NULL COMMENT '커스텀 강의 시작 시간', - `end_time` INT UNSIGNED NULL COMMENT '커스텀 강의 종료 시간', - `place` VARCHAR(255) NULL COMMENT '강의 장소', - `lecture_information_id` INT UNSIGNED NULL COMMENT 'lecture_information 고유 id', - `timetable_lecture_id` INT UNSIGNED NOT NULL COMMENT 'timetable_lecture 고유 id', - PRIMARY KEY (id), - INDEX(timetable_lecture_id) -) diff --git a/src/main/resources/db/migration/V110__create_lecture_information_table.sql b/src/main/resources/db/migration/V110__create_lecture_information_table.sql deleted file mode 100644 index 5751f428a7..0000000000 --- a/src/main/resources/db/migration/V110__create_lecture_information_table.sql +++ /dev/null @@ -1,8 +0,0 @@ -CREATE TABLE IF NOT EXISTS `koin`.`lecture_information`( - `id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '고유 id', - `lecture_id` int UNSIGNED NOT NULL COMMENT 'lecture 고유 id', - `start_time` int NULL COMMENT '정규 강의 시작 시간', - `end_time` int NULL COMMENT '정규 강의 마감 시간', - PRIMARY KEY (`id`), - index (`lecture_id`) -); diff --git a/src/main/resources/db/migration/V111__add_array_class_time_normalization_procedure.sql b/src/main/resources/db/migration/V111__add_array_class_time_normalization_procedure.sql deleted file mode 100644 index b5d5c6c643..0000000000 --- a/src/main/resources/db/migration/V111__add_array_class_time_normalization_procedure.sql +++ /dev/null @@ -1,53 +0,0 @@ -DELIMITER $$ - -CREATE PROCEDURE array_class_time_normalization ( - IN_LECTURE_ID int unsigned -) -BEGIN - -- 변수 선언 - DECLARE IN_CLASS_TIME varchar(255); - DECLARE current_class_time int; - DECLARE prev_class_time int DEFAULT NULL; - DECLARE start_class_time int DEFAULT NULL; - DECLARE end_class_time int DEFAULT NULL; - DECLARE idx int DEFAULT 1; - DECLARE count int DEFAULT 1; - - -- class_time 가져오기 - SELECT class_time INTO IN_CLASS_TIME - FROM lectures - WHERE id = IN_LECTURE_ID; - - -- 대괄호 앞 뒤 삭제 - SET IN_CLASS_TIME = REPLACE(REPLACE(IN_CLASS_TIME, '[', ''), ']', ''); - - -- 강의 시간이 있는 경우에만 로직 실행 - IF LENGTH(IN_CLASS_TIME) != 0 THEN - -- 총 실행 횟수, (현재 길이 - 콤마를 없앴을 때의 길이 + 1 = 총 시간 개수) - SET count = LENGTH(IN_CLASS_TIME) - LENGTH(REPLACE(IN_CLASS_TIME, ',', '')) + 1; - WHILE idx <= count DO - -- 인덱스에 해당하는 시간 가져오기 - SET current_class_time = CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(IN_CLASS_TIME, ',', idx), ',', -1) AS UNSIGNED); - - -- 초기 시작 시간 설정 및 연속 시간 체크 - IF prev_class_time IS NULL OR current_class_time != prev_class_time + 1 THEN - IF start_class_time IS NOT NULL THEN - INSERT INTO lecture_information (lecture_id, start_time, end_time) VALUES (IN_LECTURE_ID, start_class_time, end_class_time); - END IF; - SET start_class_time = current_class_time; - END IF; - - -- 다음 시간 저장 - SET end_class_time = current_class_time; - SET prev_class_time = current_class_time; - SET idx = idx + 1; - END WHILE; - - -- 마지막 범위 추가 - IF start_class_time IS NOT NULL THEN - INSERT INTO lecture_information (lecture_id, start_time, end_time) VALUES (IN_LECTURE_ID, start_class_time, end_class_time); - END IF; - END IF; - -END $$ -DELIMITER ; diff --git a/src/main/resources/db/migration/V112__add_call_array_class_time_normalization_procedure.sql b/src/main/resources/db/migration/V112__add_call_array_class_time_normalization_procedure.sql deleted file mode 100644 index cbbc154ae0..0000000000 --- a/src/main/resources/db/migration/V112__add_call_array_class_time_normalization_procedure.sql +++ /dev/null @@ -1,71 +0,0 @@ -DELIMITER $$ - -CREATE PROCEDURE call_array_class_time_normalization( - IN_SEMESTER_DATE VARCHAR(10) -) -BEGIN - DECLARE done INT DEFAULT 0; - DECLARE lecture_id INT; - DECLARE flag INT DEFAULT 0; - - -- 커서 선언 - DECLARE cur CURSOR FOR - SELECT id FROM lectures - where semester_date = IN_SEMESTER_DATE; - - -- 종료 핸들러 정의 - DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1; - - -- 커서 열기 - OPEN cur; - - lecture_loop: LOOP - FETCH cur INTO lecture_id; -- 여기서 반환값이 없으면 에러가 발생 -> 이를 종료 핸들러가 캐치 - IF flag THEN -- 데이터가 없으면 루프 종료 - LEAVE lecture_loop; - END IF; - - CALL array_class_time_normalization(lecture_id); -END LOOP; - - -- 커서 닫기 - CLOSE cur; -END$$ - -DELIMITER ; - --- 2019 -CALL call_array_class_time_normalization("20191"); -CALL call_array_class_time_normalization("2019-여름"); -CALL call_array_class_time_normalization("20192"); -CALL call_array_class_time_normalization("2019-겨울"); - --- 2020 -CALL call_array_class_time_normalization("20201"); -CALL call_array_class_time_normalization("2020-여름"); -CALL call_array_class_time_normalization("20202"); -CALL call_array_class_time_normalization("2020-겨울"); - --- 2021 -CALL call_array_class_time_normalization("20211"); -CALL call_array_class_time_normalization("2021-여름"); -CALL call_array_class_time_normalization("20212"); -CALL call_array_class_time_normalization("2021-겨울"); - --- 2022 -CALL call_array_class_time_normalization("20221"); -CALL call_array_class_time_normalization("2022-여름"); -CALL call_array_class_time_normalization("20222"); -CALL call_array_class_time_normalization("2022-겨울"); - --- 2023 -CALL call_array_class_time_normalization("20231"); -CALL call_array_class_time_normalization("2023-여름"); -CALL call_array_class_time_normalization("20232"); -CALL call_array_class_time_normalization("2023-겨울"); - --- 2024 -CALL call_array_class_time_normalization("20241"); -CALL call_array_class_time_normalization("2024-여름"); -CALL call_array_class_time_normalization("20242"); -CALL call_array_class_time_normalization("2024-겨울"); From c650c6ee54805fef52418f3e9123c820d1837187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 4 Jan 2025 01:14:07 +0900 Subject: [PATCH 46/61] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/timetableV3/dto/response/LectureInfoResponse.java | 4 ++-- .../koin/domain/timetableV3/utils/ClassPlaceUtils.java | 4 ++-- .../koin/domain/timetableV3/utils/ClassTimeUtils.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java index 418feef106..23aa00c166 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java @@ -32,7 +32,7 @@ public record LectureInfoResponse( ) { private static final String EMPTY_PLACE = ""; - // 역정규화 된 정유 강의 정보 정규화 하는 메소드 + // 역정규화 된 정규 강의 정보를 정규화 하는 메소드 public static List getRegularLectureInfo(String classTime, String classPlace) { List classTimes = parseToIntegerList(classTime); List response = new ArrayList<>(); @@ -66,7 +66,7 @@ public static List getRegularLectureInfo(String classTime, return response; } - // 역정규화 된 커스텀 강의 정부 정규화 하는 메소드 + // 역정규화 된 커스텀 강의 정보를 정규화 하는 메소드 public static List getCustomLectureInfo(String classTime, String classPlace) { List classTimes = parseToIntegerList(classTime); List response = new ArrayList<>(); diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java index daa7247799..af0747a7e7 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java @@ -20,7 +20,7 @@ public static List parseToStringList(String classPlace) { .toList(); } - // 정규 강의 장소 조인 + // 정규 강의 장소 역정규화 public static String parseToString(List classPlaces) { StringBuilder classPlaceSegment = new StringBuilder(); for (int index = 0; index < classPlaces.size(); index++) { @@ -32,7 +32,7 @@ public static String parseToString(List classPlaces) { return classPlaceSegment.toString(); } - // 커스텀 강의 장소 조인 + // 커스텀 강의 장소 역정규화 public static String joinClassPlaces(List lectureInfos) { StringBuilder classPlaces = new StringBuilder(); for (int index = 0; index < lectureInfos.size(); index++) { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java index d433c327ee..9b0f251d0f 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java @@ -32,7 +32,7 @@ public static Integer calcWeek(Integer startTime) { return 0; } - // 커스텀 강의 시간 조인 + // 커스텀 강의 시간 역정규화 public static String joinClassTimes(List lectureInfos) { List classTimes = new ArrayList<>(); From fb84bc3b846250997131a8420f9e7b1a2b47c00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 4 Jan 2025 01:26:11 +0900 Subject: [PATCH 47/61] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koin/domain/timetableV3/utils/ClassPlaceUtils.java | 1 + .../koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java index af0747a7e7..4145a626d8 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java @@ -14,6 +14,7 @@ public class ClassPlaceUtils { private static final String CLASSPLACE_SEPARATOR = ", "; + // 문자열 강의 장소 리스트로 변환 public static List parseToStringList(String classPlace) { return Stream.of(classPlace.split(",")) .map(String::strip) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java index 9b0f251d0f..b9e5dbff33 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java @@ -15,7 +15,7 @@ public class ClassTimeUtils { private static final Integer DIVIDE_TIME_UNIT = 100; private static final Integer CLASSTIME_SEPARATOR = -1; - // 정규 강의 시간 리스트로 변환 + // 문자열 강의 시간 리스트로 변환 public static List parseToIntegerList(String classTime) { return Stream.of(classTime.replaceAll("[\\[\\]]", "").split(",")) .map(String::strip) From 7200c3e46c94fe69801f3d5bfc79c328439a8ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 4 Jan 2025 01:49:34 +0900 Subject: [PATCH 48/61] =?UTF-8?q?fix:=20dto=20=EC=9D=98=EC=A1=B4=EC=84=B1?= =?UTF-8?q?=20=EB=81=8A=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimetableCustomLectureCreateRequest.java | 35 ++++++++++++-- .../TimetableCustomLectureUpdateRequest.java | 29 ++++++++++++ .../TimetableRegularLectureUpdateRequest.java | 11 +++++ .../dto/response/LectureInfoResponse.java | 11 ++++- .../TimetableCustomLectureServiceV3.java | 6 +-- .../TimetableRegularLectureServiceV3.java | 6 +-- .../timetableV3/utils/ClassPlaceUtils.java | 47 ------------------- .../timetableV3/utils/ClassTimeUtils.java | 20 -------- 8 files changed, 85 insertions(+), 80 deletions(-) delete mode 100644 src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java index e224447561..5529e4abf6 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java @@ -1,11 +1,10 @@ package in.koreatech.koin.domain.timetableV3.dto.request; import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; -import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.joinClassPlaces; -import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.joinClassTimes; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; +import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.annotation.JsonNaming; @@ -51,6 +50,34 @@ public record InnerTimeTableCustomLectureRequest( String memo ) { + // 커스텀 강의 장소 역정규화 + public String joinClassPlaces() { + StringBuilder classPlaces = new StringBuilder(); + for (int index = 0; index < lectureInfos.size(); index++) { + if (index > 0) { + classPlaces.append(", "); + } + classPlaces.append(lectureInfos.get(index).place()); + } + return classPlaces.toString(); + } + + // 커스텀 강의 시간 역정규화 + public String joinClassTimes() { + List classTimes = new ArrayList<>(); + + for (int index = 0; index < lectureInfos.size(); index++) { + if (index > 0) classTimes.add(-1); + + int startTime = lectureInfos.get(index).startTime(); + int endTime = lectureInfos.get(index).endTime(); + + while (startTime <= endTime) { + classTimes.add(startTime++); + } + } + return classTimes.toString(); + } } public TimetableLecture toTimetableLecture(TimetableFrame frame) { @@ -59,8 +86,8 @@ public TimetableLecture toTimetableLecture(TimetableFrame frame) { .professor(timetableLecture.professor) .grades(timetableLecture.grades) .memo(timetableLecture.memo) - .classTime(joinClassTimes(timetableLecture.lectureInfos)) - .classPlace(joinClassPlaces(timetableLecture.lectureInfos)) + .classTime(timetableLecture.joinClassTimes()) + .classPlace(timetableLecture.joinClassPlaces()) .timetableFrame(frame) .build(); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java index acb08dd1ba..d7677d0df8 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java @@ -4,6 +4,7 @@ import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; +import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.annotation.JsonNaming; @@ -43,6 +44,34 @@ public record InnerTimeTableCustomLectureRequest( String professor ) { + // 커스텀 강의 장소 역정규화 + public String joinClassPlaces() { + StringBuilder classPlaces = new StringBuilder(); + for (int index = 0; index < lectureInfos.size(); index++) { + if (index > 0) { + classPlaces.append(", "); + } + classPlaces.append(lectureInfos.get(index).place()); + } + return classPlaces.toString(); + } + + // 커스텀 강의 시간 역정규화 + public String joinClassTimes() { + List classTimes = new ArrayList<>(); + + for (int index = 0; index < lectureInfos.size(); index++) { + if (index > 0) classTimes.add(-1); + + int startTime = lectureInfos.get(index).startTime(); + int endTime = lectureInfos.get(index).endTime(); + + while (startTime <= endTime) { + classTimes.add(startTime++); + } + } + return classTimes.toString(); + } } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java index a606472e94..55e0850a96 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java @@ -51,5 +51,16 @@ public record ClassPlace( ) { } + + public String classPlacesToString() { + StringBuilder classPlaceSegment = new StringBuilder(); + for (int index = 0; index < classPlaces.size(); index++) { + if (index > 0) { + classPlaceSegment.append(", "); + } + classPlaceSegment.append(classPlaces.get(index).classPlace()); + } + return classPlaceSegment.toString(); + } } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java index 23aa00c166..10d7dd2a3d 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java @@ -1,6 +1,5 @@ package in.koreatech.koin.domain.timetableV3.dto.response; -import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.parseToStringList; import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.calcWeek; import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.parseToIntegerList; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; @@ -10,6 +9,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.stream.Stream; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; @@ -114,7 +114,14 @@ private static List getClassPlaces(String classPlace, List clas } return parseToStringList(classPlace); } - + + // 문자열 강의 장소 리스트로 변환 + private static List parseToStringList(String classPlace) { + return Stream.of(classPlace.split(",")) + .map(String::strip) + .toList(); + } + private static void addLectureInfo( List response, Integer startTime, Integer endTime, String classPlace ) { diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index f2c909032f..dc0b175c56 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -3,8 +3,6 @@ import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; -import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.joinClassPlaces; -import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.joinClassTimes; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -48,8 +46,8 @@ public TimetableLectureResponseV3 updateTimetablesCustomLecture( timetableLecture.customLectureUpdate( request.timetableLecture().classTitle(), request.timetableLecture().professor(), - joinClassTimes(request.timetableLecture().lectureInfos()), - joinClassPlaces(request.timetableLecture().lectureInfos()) + request.timetableLecture().joinClassTimes(), + request.timetableLecture().joinClassPlaces() ); timetableLectureRepositoryV3.save(timetableLecture); diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index 1e2aafcdf5..d7d1d4e7ff 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -3,7 +3,6 @@ import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateGradesMainFrame; import static in.koreatech.koin.domain.timetableV2.util.GradeCalculator.calculateTotalGrades; import static in.koreatech.koin.domain.timetableV2.validation.TimetableFrameValidate.validateUserAuthorization; -import static in.koreatech.koin.domain.timetableV3.utils.ClassPlaceUtils.parseToString; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -47,10 +46,11 @@ public TimetableLectureResponseV3 updateTimetablesRegularLecture( TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); validateUserAuthorization(frame.getUser().getId(), userId); - TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id());; + TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); + ; timetableLecture.regularLectureUpdate( request.timetableLecture().classTitle(), - parseToString(request.timetableLecture().classPlaces()) + request.timetableLecture().classPlacesToString() ); timetableLectureRepositoryV3.save(timetableLecture); diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java deleted file mode 100644 index 4145a626d8..0000000000 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassPlaceUtils.java +++ /dev/null @@ -1,47 +0,0 @@ -package in.koreatech.koin.domain.timetableV3.utils; - -import static in.koreatech.koin.domain.timetableV3.dto.request.TimetableRegularLectureUpdateRequest.InnerTimeTableRegularLectureRequest.ClassPlace; -import static lombok.AccessLevel.PRIVATE; - -import java.util.List; -import java.util.stream.Stream; - -import in.koreatech.koin.domain.timetableV3.dto.request.LectureInfoRequest; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = PRIVATE) -public class ClassPlaceUtils { - - private static final String CLASSPLACE_SEPARATOR = ", "; - - // 문자열 강의 장소 리스트로 변환 - public static List parseToStringList(String classPlace) { - return Stream.of(classPlace.split(",")) - .map(String::strip) - .toList(); - } - - // 정규 강의 장소 역정규화 - public static String parseToString(List classPlaces) { - StringBuilder classPlaceSegment = new StringBuilder(); - for (int index = 0; index < classPlaces.size(); index++) { - if (index > 0) { - classPlaceSegment.append(CLASSPLACE_SEPARATOR); - } - classPlaceSegment.append(classPlaces.get(index).classPlace()); - } - return classPlaceSegment.toString(); - } - - // 커스텀 강의 장소 역정규화 - public static String joinClassPlaces(List lectureInfos) { - StringBuilder classPlaces = new StringBuilder(); - for (int index = 0; index < lectureInfos.size(); index++) { - if (index > 0) { - classPlaces.append(CLASSPLACE_SEPARATOR); - } - classPlaces.append(lectureInfos.get(index).place()); - } - return classPlaces.toString(); - } -} diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java index b9e5dbff33..48ee00f9ec 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/utils/ClassTimeUtils.java @@ -2,18 +2,15 @@ import static lombok.AccessLevel.PRIVATE; -import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; -import in.koreatech.koin.domain.timetableV3.dto.request.LectureInfoRequest; import lombok.NoArgsConstructor; @NoArgsConstructor(access = PRIVATE) public class ClassTimeUtils { private static final Integer DIVIDE_TIME_UNIT = 100; - private static final Integer CLASSTIME_SEPARATOR = -1; // 문자열 강의 시간 리스트로 변환 public static List parseToIntegerList(String classTime) { @@ -31,21 +28,4 @@ public static Integer calcWeek(Integer startTime) { } return 0; } - - // 커스텀 강의 시간 역정규화 - public static String joinClassTimes(List lectureInfos) { - List classTimes = new ArrayList<>(); - - for (int index = 0; index < lectureInfos.size(); index++) { - if (index > 0) classTimes.add(CLASSTIME_SEPARATOR); - - int startTime = lectureInfos.get(index).startTime(); - int endTime = lectureInfos.get(index).endTime(); - - while (startTime <= endTime) { - classTimes.add(startTime++); - } - } - return classTimes.toString(); - } } From 86a70ad8a1a73059fb679924092d048108a7baac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 4 Jan 2025 11:40:31 +0900 Subject: [PATCH 49/61] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/timetableV3/controller/LectureControllerV3.java | 5 +++-- .../domain/timetableV3/dto/response/LectureResponseV3.java | 1 - .../koin/domain/timetableV3/service/LectureServiceV3.java | 4 ++-- .../service/TimetableCustomLectureServiceV3.java | 1 + .../service/TimetableRegularLectureServiceV3.java | 4 ++-- .../koin/acceptance/TimetableLectureV3ApiTest.java | 7 ++++--- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java index b0739746e0..148d147a25 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java @@ -4,6 +4,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; @@ -19,9 +20,9 @@ public class LectureControllerV3 implements LectureApiV3 { // TODO. Semester v3 올라가면 파라미터 변경하기 @GetMapping("/v3/lectures") public ResponseEntity> getLectures( - String semesterDate + @RequestParam(name = "semester_date") String semester ) { - List response = lectureServiceV3.getLectures(semesterDate); + List response = lectureServiceV3.getLectures(semester); return ResponseEntity.ok(response); } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java index 252cd83669..9673279216 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java @@ -92,7 +92,6 @@ public static List from(String classTime) { if (!Objects.isNull(startTime)) { addLectureInfo(response, startTime, endTime); } - addLectureInfo(response, startTime, endTime); } return response; } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java index 285f571f21..86dea1edfa 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java @@ -14,8 +14,8 @@ public class LectureServiceV3 { private final LectureRepositoryV3 lectureRepositoryV3; - public List getLectures(String semesterDate) { - return lectureRepositoryV3.findBySemester(semesterDate).stream() + public List getLectures(String semester) { + return lectureRepositoryV3.findBySemester(semester).stream() .map(LectureResponseV3::from) .toList(); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index dc0b175c56..9a54f7e930 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -31,6 +31,7 @@ public TimetableLectureResponseV3 createTimetablesCustomLecture( TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); validateUserAuthorization(frame.getUser().getId(), userId); TimetableLecture timetableLecture = request.toTimetableLecture(frame); + frame.addTimeTableLecture(timetableLecture); timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index d7d1d4e7ff..6202e8146e 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -35,6 +35,7 @@ public TimetableLectureResponseV3 createTimetablesRegularLecture( validateUserAuthorization(frame.getUser().getId(), userId); Lecture lecture = lectureRepositoryV3.getById(request.lectureId()); TimetableLecture timetableLecture = request.toTimetableLecture(frame, lecture); + frame.addTimeTableLecture(timetableLecture); timetableLectureRepositoryV3.save(timetableLecture); return getTimetableLectureResponse(userId, frame); } @@ -46,8 +47,7 @@ public TimetableLectureResponseV3 updateTimetablesRegularLecture( TimetableFrame frame = timetableFrameRepositoryV3.getById(request.timetableFrameId()); validateUserAuthorization(frame.getUser().getId(), userId); - TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); - ; + TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id());; timetableLecture.regularLectureUpdate( request.timetableLecture().classTitle(), request.timetableLecture().classPlacesToString() diff --git a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java index 5bf2686dd3..4f0f073172 100644 --- a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java @@ -64,8 +64,8 @@ void setup() { .header("Authorization", "Bearer " + token) .content(""" { - "timetable_frame_id" : 1, - "lecture_id" : 1 + "timetable_frame_id": 1, + "lecture_id": 1 } """) .contentType(MediaType.APPLICATION_JSON) @@ -85,7 +85,8 @@ void setup() { { "week": 0, "start_time": 12, - "end_time": 15 + "end_time": 15, + "place": "" }, { "week": 2, From cf8fbf40930d6ce0764e9f58c5023364f23afed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 4 Jan 2025 12:01:38 +0900 Subject: [PATCH 50/61] =?UTF-8?q?fix:=20=EC=A0=95=EA=B7=9C=20=EA=B0=95?= =?UTF-8?q?=EC=9D=98=20=EC=88=98=EC=A0=95=EA=B8=B0=EB=8A=A5=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/LectureInfoResponse.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java index 10d7dd2a3d..8b403987fe 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java @@ -52,7 +52,12 @@ public static List getRegularLectureInfo(String classTime, for (Integer time : classTimes) { if (Objects.isNull(prevTime) || time != prevTime + 1) { if (!Objects.isNull(startTime)) { - addLectureInfo(response, startTime, endTime, classPlaces.get(index++)); + if (index + 1 > classPlaces.size()) { + addLectureInfo(response, startTime, endTime, EMPTY_PLACE); + } + else { + addLectureInfo(response, startTime, endTime, classPlaces.get(index++)); + } } startTime = time; } @@ -61,7 +66,12 @@ public static List getRegularLectureInfo(String classTime, } if (!Objects.isNull(startTime)) { - addLectureInfo(response, startTime, endTime, classPlaces.get(index)); + if (index + 1 > classPlaces.size()) { + addLectureInfo(response, startTime, endTime, EMPTY_PLACE); + } + else { + addLectureInfo(response, startTime, endTime, classPlaces.get(index)); + } } return response; } From dcc563278abd733fbef9f1ed93501740237953f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sat, 4 Jan 2025 12:01:51 +0900 Subject: [PATCH 51/61] =?UTF-8?q?docs:=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=EC=BD=94=EB=93=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV3/controller/TimetableCustomLectureApiV3.java | 4 ++-- .../timetableV3/controller/TimetableRegularLectureApiV3.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java index 0904c2b849..3ca4308ffb 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableCustomLectureApiV3.java @@ -25,7 +25,7 @@ public interface TimetableCustomLectureApiV3 { @ApiResponses( value = { - @ApiResponse(responseCode = "201"), + @ApiResponse(responseCode = "200"), @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), @@ -42,7 +42,7 @@ ResponseEntity createTimetablesCustomLecture( @ApiResponses( value = { - @ApiResponse(responseCode = "201"), + @ApiResponse(responseCode = "200"), @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java index 02c4d09511..ae80fae46d 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableRegularLectureApiV3.java @@ -25,7 +25,7 @@ public interface TimetableRegularLectureApiV3 { @ApiResponses( value = { - @ApiResponse(responseCode = "201"), + @ApiResponse(responseCode = "200"), @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), @@ -42,7 +42,7 @@ ResponseEntity createTimetablesRegularLecture( @ApiResponses( value = { - @ApiResponse(responseCode = "201"), + @ApiResponse(responseCode = "200"), @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), From fe17cc87a81374e9533fe3479ddda940869e7e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 5 Jan 2025 00:57:09 +0900 Subject: [PATCH 52/61] =?UTF-8?q?chore:=20lecture=20API=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/timetableV3/controller/LectureApiV3.java | 5 ++++- .../timetableV3/controller/LectureControllerV3.java | 7 ++++--- .../timetableV3/controller/SemesterControllerV3.java | 2 +- .../timetableV3/repository/SemesterRepositoryV3.java | 10 ++++++++++ .../domain/timetableV3/service/LectureServiceV3.java | 9 +++++++-- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java index d68dd7eeb2..8daf54998c 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java @@ -4,8 +4,10 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; +import in.koreatech.koin.domain.timetableV3.model.Term; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -27,6 +29,7 @@ public interface LectureApiV3 { @Operation(summary = "정규 강의 목록 조회") @GetMapping("/v3/lectures") ResponseEntity> getLectures( - String semesterDate + @RequestParam(name = "year") Integer year, + @RequestParam(name = "term") Term term ); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java index 148d147a25..c06c1139d3 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java @@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.RestController; import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; +import in.koreatech.koin.domain.timetableV3.model.Term; import in.koreatech.koin.domain.timetableV3.service.LectureServiceV3; import lombok.RequiredArgsConstructor; @@ -17,12 +18,12 @@ public class LectureControllerV3 implements LectureApiV3 { private final LectureServiceV3 lectureServiceV3; - // TODO. Semester v3 올라가면 파라미터 변경하기 @GetMapping("/v3/lectures") public ResponseEntity> getLectures( - @RequestParam(name = "semester_date") String semester + @RequestParam(name = "year") Integer year, + @RequestParam(name = "term") Term term ) { - List response = lectureServiceV3.getLectures(semester); + List response = lectureServiceV3.getLectures(year, term); return ResponseEntity.ok(response); } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/SemesterControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/SemesterControllerV3.java index ea6c0ba0dc..7105d7736a 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/SemesterControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/SemesterControllerV3.java @@ -16,7 +16,7 @@ @RestController @RequiredArgsConstructor -public class SemesterControllerV3 { +public class SemesterControllerV3 implements SemesterApiV3 { private final SemesterServiceV3 semesterServiceV3; diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/SemesterRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/SemesterRepositoryV3.java index dd8454dae3..bf46412a34 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/SemesterRepositoryV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/SemesterRepositoryV3.java @@ -1,14 +1,24 @@ package in.koreatech.koin.domain.timetableV3.repository; import java.util.List; +import java.util.Optional; import org.springframework.data.repository.Repository; +import in.koreatech.koin.domain.timetable.exception.SemesterNotFoundException; import in.koreatech.koin.domain.timetable.model.Semester; +import in.koreatech.koin.domain.timetableV3.model.Term; public interface SemesterRepositoryV3 extends Repository { List findAll(); Semester save(Semester semester); + + Optional findByYearAndTerm(Integer year, Term term); + + default Semester getByYearAndTerm(Integer year, Term term) { + return findByYearAndTerm(year, term) + .orElseThrow(() -> SemesterNotFoundException.withDetail("year : " + year + "term : " + term.getDescription())); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java index 86dea1edfa..40e0001c72 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java @@ -4,8 +4,11 @@ import org.springframework.stereotype.Service; +import in.koreatech.koin.domain.timetable.model.Semester; import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; +import in.koreatech.koin.domain.timetableV3.model.Term; import in.koreatech.koin.domain.timetableV3.repository.LectureRepositoryV3; +import in.koreatech.koin.domain.timetableV3.repository.SemesterRepositoryV3; import lombok.RequiredArgsConstructor; @Service @@ -13,9 +16,11 @@ public class LectureServiceV3 { private final LectureRepositoryV3 lectureRepositoryV3; + private final SemesterRepositoryV3 semesterRepositoryV3; - public List getLectures(String semester) { - return lectureRepositoryV3.findBySemester(semester).stream() + public List getLectures(Integer year, Term term) { + Semester semester = semesterRepositoryV3.getByYearAndTerm(year, term); + return lectureRepositoryV3.findBySemester(semester.getSemester()).stream() .map(LectureResponseV3::from) .toList(); } From e999543b68ef5c6972ef740b5d2723e3cc429b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 5 Jan 2025 01:04:45 +0900 Subject: [PATCH 53/61] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../in/koreatech/koin/acceptance/LectureApiTest.java | 12 +++++++++--- .../koin/acceptance/TimetableLectureV3ApiTest.java | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java b/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java index 071f55116b..d6f9bfcf02 100644 --- a/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java @@ -12,7 +12,9 @@ import org.springframework.transaction.annotation.Transactional; import in.koreatech.koin.AcceptanceTest; +import in.koreatech.koin.domain.timetable.model.Semester; import in.koreatech.koin.fixture.LectureFixture; +import in.koreatech.koin.fixture.SemesterFixture; @SuppressWarnings("NonAsciiCharacters") @Transactional @@ -22,6 +24,9 @@ public class LectureApiTest extends AcceptanceTest { @Autowired private LectureFixture lectureFixture; + @Autowired + private SemesterFixture semesterFixture; + @BeforeAll void setup() { clear(); @@ -29,12 +34,13 @@ void setup() { @Test void 특정_학기_강의를_조회한다() throws Exception { - String semester = "20201"; - lectureFixture.HRD_개론(semester); + Semester semester = semesterFixture.semester_2020년도_1학기(); + lectureFixture.HRD_개론(semester.getSemester()); mockMvc.perform( get("/v3/lectures") - .param("semester_date", semester) + .param("year", String.valueOf(semester.getYear())) + .param("term", String.valueOf(semester.getTerm())) .contentType(MediaType.APPLICATION_JSON) ) .andExpect(status().isOk()) diff --git a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java index 4f0f073172..fef4f7161e 100644 --- a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java @@ -51,7 +51,7 @@ void setup() { clear(); user = userFixture.준호_학생().getUser(); token = userFixture.getToken(user); - semester = semesterFixture.semester("20192"); + semester = semesterFixture.semester_2019년도_2학기(); } @Test From 70d4a300735cf5a654db21a56c564747bc3dfd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 5 Jan 2025 02:58:36 +0900 Subject: [PATCH 54/61] =?UTF-8?q?chore:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/TimetableCustomLectureCreateRequest.java | 12 ++++-------- .../request/TimetableCustomLectureUpdateRequest.java | 12 ++++-------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java index 5529e4abf6..ec5684e014 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureCreateRequest.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import com.fasterxml.jackson.databind.annotation.JsonNaming; @@ -52,14 +53,9 @@ public record InnerTimeTableCustomLectureRequest( // 커스텀 강의 장소 역정규화 public String joinClassPlaces() { - StringBuilder classPlaces = new StringBuilder(); - for (int index = 0; index < lectureInfos.size(); index++) { - if (index > 0) { - classPlaces.append(", "); - } - classPlaces.append(lectureInfos.get(index).place()); - } - return classPlaces.toString(); + return lectureInfos.stream() + .map(LectureInfoRequest::place) + .collect(Collectors.joining(", ")); } // 커스텀 강의 시간 역정규화 diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java index d7677d0df8..7d718e91ee 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableCustomLectureUpdateRequest.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import com.fasterxml.jackson.databind.annotation.JsonNaming; @@ -46,14 +47,9 @@ public record InnerTimeTableCustomLectureRequest( // 커스텀 강의 장소 역정규화 public String joinClassPlaces() { - StringBuilder classPlaces = new StringBuilder(); - for (int index = 0; index < lectureInfos.size(); index++) { - if (index > 0) { - classPlaces.append(", "); - } - classPlaces.append(lectureInfos.get(index).place()); - } - return classPlaces.toString(); + return lectureInfos.stream() + .map(LectureInfoRequest::place) + .collect(Collectors.joining(", ")); } // 커스텀 강의 시간 역정규화 From 3ba3955bf6aaefd4b884bcc8aaa38349ef101616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 5 Jan 2025 02:58:54 +0900 Subject: [PATCH 55/61] =?UTF-8?q?chore:=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EC=A0=95=EA=B7=9C=ED=99=94=20=EB=A9=94=EC=86=8C=EB=93=9C=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 --- .../dto/response/LectureInfoResponse.java | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java index ed5b82056b..6593c59e49 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java @@ -1,5 +1,6 @@ package in.koreatech.koin.domain.timetableV3.dto.response; +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.calcWeek; import static in.koreatech.koin.domain.timetableV3.utils.ClassTimeUtils.parseToIntegerList; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED; @@ -11,12 +12,11 @@ import java.util.Objects; import java.util.stream.Stream; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import io.swagger.v3.oas.annotations.media.Schema; -@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class) +@JsonNaming(value = SnakeCaseStrategy.class) public record LectureInfoResponse( @Schema(description = "요일 id", example = "0", requiredMode = REQUIRED) Integer week, @@ -51,12 +51,10 @@ public static List getRegularLectureInfo(String classTime, for (int index = 1; index < classTimes.size(); index++) { if (classTimes.get(index) == endTime + 1) { endTime = classTimes.get(index); - } - else { + } else { if (classPlaceIndex + 1 > classPlaces.size()) { addLectureInfo(response, startTime, endTime, EMPTY_PLACE); - } - else { + } else { addLectureInfo(response, startTime, endTime, classPlaces.get(classPlaceIndex++)); } startTime = classTimes.get(index); @@ -66,8 +64,7 @@ public static List getRegularLectureInfo(String classTime, if (classPlaceIndex + 1 > classPlaces.size()) { addLectureInfo(response, startTime, endTime, EMPTY_PLACE); - } - else { + } else { addLectureInfo(response, startTime, endTime, classPlaces.get(classPlaceIndex)); } return response; @@ -80,34 +77,33 @@ public static List getCustomLectureInfo(String classTime, S List classPlaces = getClassPlaces(classPlace, classTimes); - Integer prevTime = null; - Integer startTime = null; - Integer endTime = null; + int startTime = classTimes.get(0); + int endTime = startTime; int placesIndex = 0; - for (int time : classTimes) { - if (Objects.isNull(prevTime)) { - startTime = time; - } + for (int index = 1; index < classTimes.size(); index++) { + int time = classTimes.get(index); - if (!Objects.isNull(prevTime) && prevTime == -1) { + if (endTime == -1) { startTime = time; - prevTime = null; - endTime = null; + endTime = startTime; + continue; } - if (time == -1) { - addLectureInfo(response, startTime, endTime, classPlaces.get(placesIndex++)); - } else if (!Objects.isNull(prevTime) && prevTime + 1 != time) { - addLectureInfo(response, startTime, endTime, classPlaces.get(placesIndex)); + if (time == endTime + 1) { + endTime = time; + } else { + if (time == -1) { + addLectureInfo(response, startTime, endTime, classPlaces.get(placesIndex++)); + } else { + addLectureInfo(response, startTime, endTime, classPlaces.get(placesIndex)); + } startTime = time; + endTime = startTime; } - - endTime = time; - prevTime = time; } - if (!Objects.isNull(startTime) && prevTime != -1) { + if (endTime != -1) { addLectureInfo(response, startTime, endTime, classPlaces.get(placesIndex)); } From 7ee4e2cc7bb8f2ac2814de71419fac3011986dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 5 Jan 2025 03:06:28 +0900 Subject: [PATCH 56/61] =?UTF-8?q?chore:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimetableRegularLectureUpdateRequest.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java index 55e0850a96..4b671680af 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/request/TimetableRegularLectureUpdateRequest.java @@ -5,6 +5,7 @@ import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; import java.util.List; +import java.util.stream.Collectors; import com.fasterxml.jackson.databind.annotation.JsonNaming; @@ -52,15 +53,11 @@ public record ClassPlace( } + // 정규 강의 장소 역정규화 메소드 public String classPlacesToString() { - StringBuilder classPlaceSegment = new StringBuilder(); - for (int index = 0; index < classPlaces.size(); index++) { - if (index > 0) { - classPlaceSegment.append(", "); - } - classPlaceSegment.append(classPlaces.get(index).classPlace()); - } - return classPlaceSegment.toString(); + return classPlaces.stream() + .map(ClassPlace::classPlace) + .collect(Collectors.joining(", ")); } } } From 1556bbe731b2b61a633a1ad2b4c229d86e5d0289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 5 Jan 2025 04:16:34 +0900 Subject: [PATCH 57/61] =?UTF-8?q?chore:=20lecture=20v3=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/timetableV3/controller/LectureApiV3.java | 6 ++---- .../timetableV3/controller/LectureControllerV3.java | 3 +-- .../koreatech/koin/domain/timetableV3/model/Term.java | 10 ++++++++++ .../domain/timetableV3/service/LectureServiceV3.java | 4 ++-- .../in/koreatech/koin/acceptance/LectureApiTest.java | 2 +- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java index 8daf54998c..a152986460 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureApiV3.java @@ -7,7 +7,6 @@ import org.springframework.web.bind.annotation.RequestParam; import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; -import in.koreatech.koin.domain.timetableV3.model.Term; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -21,8 +20,7 @@ public interface LectureApiV3 { @ApiResponses( value = { @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), - @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(hidden = true))), @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))), } ) @@ -30,6 +28,6 @@ public interface LectureApiV3 { @GetMapping("/v3/lectures") ResponseEntity> getLectures( @RequestParam(name = "year") Integer year, - @RequestParam(name = "term") Term term + @RequestParam(name = "term") String term ); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java index c06c1139d3..57ce01a3d4 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/LectureControllerV3.java @@ -8,7 +8,6 @@ import org.springframework.web.bind.annotation.RestController; import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; -import in.koreatech.koin.domain.timetableV3.model.Term; import in.koreatech.koin.domain.timetableV3.service.LectureServiceV3; import lombok.RequiredArgsConstructor; @@ -21,7 +20,7 @@ public class LectureControllerV3 implements LectureApiV3 { @GetMapping("/v3/lectures") public ResponseEntity> getLectures( @RequestParam(name = "year") Integer year, - @RequestParam(name = "term") Term term + @RequestParam(name = "term") String term ) { List response = lectureServiceV3.getLectures(year, term); return ResponseEntity.ok(response); diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/model/Term.java b/src/main/java/in/koreatech/koin/domain/timetableV3/model/Term.java index 6f65b22800..76eb3a07a2 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/model/Term.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/model/Term.java @@ -1,5 +1,6 @@ package in.koreatech.koin.domain.timetableV3.model; +import in.koreatech.koin.global.exception.KoinIllegalArgumentException; import lombok.Getter; @Getter @@ -16,4 +17,13 @@ public enum Term { this.description = description; this.priority = priority; } + + public static Term fromDescription(String description) { + for (Term term : Term.values()) { + if (term.description.equals(description)) { + return term; + } + } + throw new KoinIllegalArgumentException("term 양식이 잘못됐습니다."); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java index 40e0001c72..2746e2eaac 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java @@ -18,8 +18,8 @@ public class LectureServiceV3 { private final LectureRepositoryV3 lectureRepositoryV3; private final SemesterRepositoryV3 semesterRepositoryV3; - public List getLectures(Integer year, Term term) { - Semester semester = semesterRepositoryV3.getByYearAndTerm(year, term); + public List getLectures(Integer year, String term) { + Semester semester = semesterRepositoryV3.getByYearAndTerm(year, Term.fromDescription(term)); return lectureRepositoryV3.findBySemester(semester.getSemester()).stream() .map(LectureResponseV3::from) .toList(); diff --git a/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java b/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java index d6f9bfcf02..ebb500a414 100644 --- a/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java @@ -40,7 +40,7 @@ void setup() { mockMvc.perform( get("/v3/lectures") .param("year", String.valueOf(semester.getYear())) - .param("term", String.valueOf(semester.getTerm())) + .param("term", String.valueOf(semester.getTerm().getDescription())) .contentType(MediaType.APPLICATION_JSON) ) .andExpect(status().isOk()) From 7f293c74ebb7e7db0b85654ff36327bd90784700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 5 Jan 2025 04:43:47 +0900 Subject: [PATCH 58/61] =?UTF-8?q?chore:=20frame=20=EB=B3=B5=EA=B5=AC=20api?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TimetableLectureApiV3.java | 20 ----- .../TimetableLectureControllerV3.java | 9 --- .../service/TimetableLectureServiceV3.java | 25 ------- .../acceptance/TimetableLectureV3ApiTest.java | 73 ------------------- 4 files changed, 127 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java index e054afbafa..6d0b48f502 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java @@ -53,24 +53,4 @@ ResponseEntity rollbackTimetableLecture( @RequestParam(name = "timetable_lectures_id") List timetableLecturesId, @Auth(permit = {STUDENT}) Integer userId ); - - @ApiResponses( - value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), - @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), - @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) - } - ) - @Operation(summary = "삭제한 시간표 프레임과 강의 복구", - description = """ - 1. 삭제된 시간표 프레임: 삭제된 시간표 프레임과 그에 속한 강의 정보를 복구합니다. \n - 2. 삭제되지 않은 시간표 프레임: 시간표 프레임에 속한 강의 정보를 복구합니다. - """) - @SecurityRequirement(name = "Jwt Authentication") - @PostMapping("/v3/timetables/frame/rollback") - ResponseEntity rollbackTimetableFrame( - @RequestParam(name = "timetable_frame_id") Integer timetableFrameId, - @Auth(permit = {STUDENT}) Integer userId - ); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java index 7ec8abff03..7e239e7d98 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java @@ -38,13 +38,4 @@ public ResponseEntity rollbackTimetableLecture( TimetableLectureResponseV3 response = lectureServiceV3.rollbackTimetableLecture(timetableLecturesId, userId); return ResponseEntity.ok(response); } - - @PostMapping("/v3/timetables/frame/rollback") - public ResponseEntity rollbackTimetableFrame( - @RequestParam(name = "timetable_frame_id") Integer timetableFrameId, - @Auth(permit = {STUDENT}) Integer userId - ) { - TimetableLectureResponseV3 response = lectureServiceV3.rollbackTimetableFrame(timetableFrameId, userId); - return ResponseEntity.ok(response); - } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java index 63323a2639..b48ebb968d 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java @@ -14,8 +14,6 @@ import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; -import in.koreatech.koin.domain.user.model.User; -import in.koreatech.koin.domain.user.repository.UserRepository; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import lombok.RequiredArgsConstructor; @@ -28,7 +26,6 @@ public class TimetableLectureServiceV3 { private EntityManager entityManager; private final TimetableFrameRepositoryV3 timetableFrameRepositoryV3; private final TimetableLectureRepositoryV3 timetableLectureRepositoryV3; - private final UserRepository userRepository; public TimetableLectureResponseV3 getTimetableLecture(Integer timetableFrameId, Integer userId) { TimetableFrame frame = timetableFrameRepositoryV3.getById(timetableFrameId); @@ -52,26 +49,4 @@ public TimetableLectureResponseV3 rollbackTimetableLecture(List timetab TimetableLecture timeTableLecture = timetableLectureRepositoryV3.getById(timetableLecturesId.get(0)); return getTimetableLectureResponse(userId, timeTableLecture.getTimetableFrame()); } - - @Transactional - public TimetableLectureResponseV3 rollbackTimetableFrame(Integer frameId, Integer userId) { - TimetableFrame timetableFrame = timetableFrameRepositoryV3.getByIdWithDeleted(frameId); - validateUserAuthorization(timetableFrame.getUser().getId(), userId); - - User user = userRepository.getById(userId); - boolean hasTimetableFrame = timetableFrameRepositoryV3.existsByUserAndSemester(user, - timetableFrame.getSemester()); - - if (!hasTimetableFrame) { - timetableFrame.updateMainFlag(true); - } - timetableFrame.undelete(); - - timetableLectureRepositoryV3.findAllByFrameIdWithDeleted(timetableFrame.getId()).stream() - .map(TimetableLecture::getId) - .map(timetableLectureRepositoryV3::getByIdWithDeleted) - .forEach(TimetableLecture::undelete); - entityManager.flush(); - return getTimetableLectureResponse(userId, timetableFrame); - } } diff --git a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java index fef4f7161e..13e96ffcdb 100644 --- a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java @@ -249,77 +249,4 @@ void setup() { } """)); } - - @Test - void 삭제된_시간표프레임과_그에_해당하는_강의를_복구한다_V3() throws Exception { - Lecture 건축구조의_이해_및_실습 = lectureFixture.건축구조의_이해_및_실습(semester.getSemester()); - Lecture HRD_개론 = lectureFixture.HRD_개론(semester.getSemester()); - TimetableFrame frame = timetableV2Fixture.시간표7(user, semester, 건축구조의_이해_및_실습, HRD_개론); - - mockMvc.perform( - post("/v3/timetables/frame/rollback") - .header("Authorization", "Bearer " + token) - .param("timetable_frame_id", String.valueOf(frame.getId())) - .contentType(MediaType.APPLICATION_JSON) - ) - .andExpect(status().isOk()) - .andExpect(content().json(""" - { - "timetable_frame_id": 1, - "timetable": [ - { - "id" : 1, - "lecture_id" : 1, - "regular_number": "25", - "code": "ARB244", - "design_score": "0", - "lecture_infos": [ - { - "week": 2, - "start_time": 200, - "end_time": 207, - "place": "" - } - ], - "memo": null, - "grades": "3", - "class_title": "건축구조의 이해 및 실습", - "lecture_class": "01", - "target": "디자 1 건축", - "professor": "황현식", - "department": "디자인ㆍ건축공학부" - }, - { - "id": 2, - "lecture_id": 2, - "regular_number": "22", - "code": "BSM590", - "design_score": "0", - "lecture_infos": [ - { - "week": 0, - "start_time": 12, - "end_time": 15 - }, - { - "week": 2, - "start_time": 210, - "end_time": 213, - "place": "" - } - ], - "memo": null, - "grades": "3", - "class_title": "컴퓨팅사고", - "lecture_class": "06", - "target": "기공1", - "professor": "박한수,최준호", - "department": "기계공학부" - } - ], - "grades": 6, - "total_grades": 6 - } - """)); - } } From 1100595e0499ea01bbf162e8b8abdbd99b9c9721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 5 Jan 2025 09:17:31 +0900 Subject: [PATCH 59/61] =?UTF-8?q?Revert=20"chore:=20frame=20=EB=B3=B5?= =?UTF-8?q?=EA=B5=AC=20api=20=EC=82=AD=EC=A0=9C"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7f293c74ebb7e7db0b85654ff36327bd90784700. --- .../controller/TimetableLectureApiV3.java | 20 +++++ .../TimetableLectureControllerV3.java | 9 +++ .../service/TimetableLectureServiceV3.java | 25 +++++++ .../acceptance/TimetableLectureV3ApiTest.java | 73 +++++++++++++++++++ 4 files changed, 127 insertions(+) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java index 6d0b48f502..e054afbafa 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureApiV3.java @@ -53,4 +53,24 @@ ResponseEntity rollbackTimetableLecture( @RequestParam(name = "timetable_lectures_id") List timetableLecturesId, @Auth(permit = {STUDENT}) Integer userId ); + + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))) + } + ) + @Operation(summary = "삭제한 시간표 프레임과 강의 복구", + description = """ + 1. 삭제된 시간표 프레임: 삭제된 시간표 프레임과 그에 속한 강의 정보를 복구합니다. \n + 2. 삭제되지 않은 시간표 프레임: 시간표 프레임에 속한 강의 정보를 복구합니다. + """) + @SecurityRequirement(name = "Jwt Authentication") + @PostMapping("/v3/timetables/frame/rollback") + ResponseEntity rollbackTimetableFrame( + @RequestParam(name = "timetable_frame_id") Integer timetableFrameId, + @Auth(permit = {STUDENT}) Integer userId + ); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java index 7e239e7d98..7ec8abff03 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/controller/TimetableLectureControllerV3.java @@ -38,4 +38,13 @@ public ResponseEntity rollbackTimetableLecture( TimetableLectureResponseV3 response = lectureServiceV3.rollbackTimetableLecture(timetableLecturesId, userId); return ResponseEntity.ok(response); } + + @PostMapping("/v3/timetables/frame/rollback") + public ResponseEntity rollbackTimetableFrame( + @RequestParam(name = "timetable_frame_id") Integer timetableFrameId, + @Auth(permit = {STUDENT}) Integer userId + ) { + TimetableLectureResponseV3 response = lectureServiceV3.rollbackTimetableFrame(timetableFrameId, userId); + return ResponseEntity.ok(response); + } } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java index b48ebb968d..63323a2639 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java @@ -14,6 +14,8 @@ import in.koreatech.koin.domain.timetableV3.dto.response.TimetableLectureResponseV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableFrameRepositoryV3; import in.koreatech.koin.domain.timetableV3.repository.TimetableLectureRepositoryV3; +import in.koreatech.koin.domain.user.model.User; +import in.koreatech.koin.domain.user.repository.UserRepository; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import lombok.RequiredArgsConstructor; @@ -26,6 +28,7 @@ public class TimetableLectureServiceV3 { private EntityManager entityManager; private final TimetableFrameRepositoryV3 timetableFrameRepositoryV3; private final TimetableLectureRepositoryV3 timetableLectureRepositoryV3; + private final UserRepository userRepository; public TimetableLectureResponseV3 getTimetableLecture(Integer timetableFrameId, Integer userId) { TimetableFrame frame = timetableFrameRepositoryV3.getById(timetableFrameId); @@ -49,4 +52,26 @@ public TimetableLectureResponseV3 rollbackTimetableLecture(List timetab TimetableLecture timeTableLecture = timetableLectureRepositoryV3.getById(timetableLecturesId.get(0)); return getTimetableLectureResponse(userId, timeTableLecture.getTimetableFrame()); } + + @Transactional + public TimetableLectureResponseV3 rollbackTimetableFrame(Integer frameId, Integer userId) { + TimetableFrame timetableFrame = timetableFrameRepositoryV3.getByIdWithDeleted(frameId); + validateUserAuthorization(timetableFrame.getUser().getId(), userId); + + User user = userRepository.getById(userId); + boolean hasTimetableFrame = timetableFrameRepositoryV3.existsByUserAndSemester(user, + timetableFrame.getSemester()); + + if (!hasTimetableFrame) { + timetableFrame.updateMainFlag(true); + } + timetableFrame.undelete(); + + timetableLectureRepositoryV3.findAllByFrameIdWithDeleted(timetableFrame.getId()).stream() + .map(TimetableLecture::getId) + .map(timetableLectureRepositoryV3::getByIdWithDeleted) + .forEach(TimetableLecture::undelete); + entityManager.flush(); + return getTimetableLectureResponse(userId, timetableFrame); + } } diff --git a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java index 13e96ffcdb..fef4f7161e 100644 --- a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java @@ -249,4 +249,77 @@ void setup() { } """)); } + + @Test + void 삭제된_시간표프레임과_그에_해당하는_강의를_복구한다_V3() throws Exception { + Lecture 건축구조의_이해_및_실습 = lectureFixture.건축구조의_이해_및_실습(semester.getSemester()); + Lecture HRD_개론 = lectureFixture.HRD_개론(semester.getSemester()); + TimetableFrame frame = timetableV2Fixture.시간표7(user, semester, 건축구조의_이해_및_실습, HRD_개론); + + mockMvc.perform( + post("/v3/timetables/frame/rollback") + .header("Authorization", "Bearer " + token) + .param("timetable_frame_id", String.valueOf(frame.getId())) + .contentType(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk()) + .andExpect(content().json(""" + { + "timetable_frame_id": 1, + "timetable": [ + { + "id" : 1, + "lecture_id" : 1, + "regular_number": "25", + "code": "ARB244", + "design_score": "0", + "lecture_infos": [ + { + "week": 2, + "start_time": 200, + "end_time": 207, + "place": "" + } + ], + "memo": null, + "grades": "3", + "class_title": "건축구조의 이해 및 실습", + "lecture_class": "01", + "target": "디자 1 건축", + "professor": "황현식", + "department": "디자인ㆍ건축공학부" + }, + { + "id": 2, + "lecture_id": 2, + "regular_number": "22", + "code": "BSM590", + "design_score": "0", + "lecture_infos": [ + { + "week": 0, + "start_time": 12, + "end_time": 15 + }, + { + "week": 2, + "start_time": 210, + "end_time": 213, + "place": "" + } + ], + "memo": null, + "grades": "3", + "class_title": "컴퓨팅사고", + "lecture_class": "06", + "target": "기공1", + "professor": "박한수,최준호", + "department": "기계공학부" + } + ], + "grades": 6, + "total_grades": 6 + } + """)); + } } From 9fb5822740162944dfdf0fb0de1845070fec6c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 5 Jan 2025 17:50:57 +0900 Subject: [PATCH 60/61] =?UTF-8?q?chore:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timetableV2/model/TimetableLecture.java | 4 ++-- .../dto/response/LectureInfoResponse.java | 4 ++-- .../dto/response/LectureResponseV3.java | 6 ++---- .../repository/LectureRepositoryV3.java | 4 ++-- .../timetableV3/service/LectureServiceV3.java | 2 ++ .../TimetableCustomLectureServiceV3.java | 2 +- .../service/TimetableLectureServiceV3.java | 1 + .../TimetableRegularLectureServiceV3.java | 2 +- .../acceptance/TimetableLectureV3ApiTest.java | 18 +++++++++--------- 9 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java index 590a7ef9c5..a6d5e5db88 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java @@ -115,14 +115,14 @@ public void undelete() { this.isDeleted = false; } - public void customLectureUpdate(String classTitle, String professor, String classTime, String classPlace) { + public void updateCustomLecture(String classTitle, String professor, String classTime, String classPlace) { this.classTitle = classTitle; this.professor = professor; this.classTime = classTime; this.classPlace = classPlace; } - public void regularLectureUpdate(String classTitle, String classPlace) { + public void updateRegularLecture(String classTitle, String classPlace) { if (!lecture.getName().equals(classTitle)) { this.classTitle = classTitle; } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java index 6593c59e49..4bb2f2fa29 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureInfoResponse.java @@ -18,8 +18,8 @@ @JsonNaming(value = SnakeCaseStrategy.class) public record LectureInfoResponse( - @Schema(description = "요일 id", example = "0", requiredMode = REQUIRED) - Integer week, + @Schema(description = "요일", example = "0", requiredMode = REQUIRED) + Integer day, @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) Integer startTime, diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java index 3d96940c63..2770230de9 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/dto/response/LectureResponseV3.java @@ -8,7 +8,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; import com.fasterxml.jackson.databind.annotation.JsonNaming; @@ -60,7 +59,7 @@ public record LectureResponseV3( @JsonNaming(value = SnakeCaseStrategy.class) public record LectureInfo( @Schema(description = "요일", example = "0", requiredMode = REQUIRED) - Integer week, + Integer day, @Schema(description = "시작 시간", example = "112", requiredMode = REQUIRED) Integer startTime, @@ -80,8 +79,7 @@ public static List from(String classTime) { for (int index = 1; index < classTimes.size(); index++) { if (classTimes.get(index) == endTime + 1) { endTime = classTimes.get(index); - } - else { + } else { addLectureInfo(response, startTime, endTime); startTime = classTimes.get(index); endTime = startTime; diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java index 2a60ab6412..05d9a7f385 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/repository/LectureRepositoryV3.java @@ -12,12 +12,12 @@ public interface LectureRepositoryV3 extends Repository { + List findBySemester(String semesterDate); + Optional findById(Integer id); default Lecture getById(Integer id) { return findById(id) .orElseThrow(() -> LectureNotFoundException.withDetail("lecture_id: " + id)); } - - List findBySemester(String semesterDate); } diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java index 2746e2eaac..8cfd7ca29d 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/LectureServiceV3.java @@ -3,6 +3,7 @@ import java.util.List; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import in.koreatech.koin.domain.timetable.model.Semester; import in.koreatech.koin.domain.timetableV3.dto.response.LectureResponseV3; @@ -13,6 +14,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class LectureServiceV3 { private final LectureRepositoryV3 lectureRepositoryV3; diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java index 9a54f7e930..da77e1c706 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableCustomLectureServiceV3.java @@ -44,7 +44,7 @@ public TimetableLectureResponseV3 updateTimetablesCustomLecture( validateUserAuthorization(frame.getUser().getId(), userId); TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id()); - timetableLecture.customLectureUpdate( + timetableLecture.updateCustomLecture( request.timetableLecture().classTitle(), request.timetableLecture().professor(), request.timetableLecture().joinClassTimes(), diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java index 63323a2639..476af65b48 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableLectureServiceV3.java @@ -22,6 +22,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class TimetableLectureServiceV3 { @PersistenceContext diff --git a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java index 6202e8146e..23431bf0df 100644 --- a/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java +++ b/src/main/java/in/koreatech/koin/domain/timetableV3/service/TimetableRegularLectureServiceV3.java @@ -48,7 +48,7 @@ public TimetableLectureResponseV3 updateTimetablesRegularLecture( validateUserAuthorization(frame.getUser().getId(), userId); TimetableLecture timetableLecture = timetableLectureRepositoryV3.getById(request.timetableLecture().id());; - timetableLecture.regularLectureUpdate( + timetableLecture.updateRegularLecture( request.timetableLecture().classTitle(), request.timetableLecture().classPlacesToString() ); diff --git a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java index fef4f7161e..c48f327b2c 100644 --- a/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/TimetableLectureV3ApiTest.java @@ -83,13 +83,13 @@ void setup() { "design_score": "0", "lecture_infos": [ { - "week": 0, + "day": 0, "start_time": 12, "end_time": 15, "place": "" }, { - "week": 2, + "day": 2, "start_time": 210, "end_time": 213, "place": "" @@ -150,7 +150,7 @@ void setup() { "design_score": null, "lecture_infos": [ { - "week": 1, + "day": 1, "start_time": 112, "end_time": 115, "place": "2공학관314" @@ -202,7 +202,7 @@ void setup() { "design_score": "0", "lecture_infos": [ { - "week": 2, + "day": 2, "start_time": 200, "end_time": 207, "place": "" @@ -224,12 +224,12 @@ void setup() { "design_score": "0", "lecture_infos": [ { - "week": 0, + "day": 0, "start_time": 12, "end_time": 15 }, { - "week": 2, + "day": 2, "start_time": 210, "end_time": 213, "place": "" @@ -275,7 +275,7 @@ void setup() { "design_score": "0", "lecture_infos": [ { - "week": 2, + "day": 2, "start_time": 200, "end_time": 207, "place": "" @@ -297,12 +297,12 @@ void setup() { "design_score": "0", "lecture_infos": [ { - "week": 0, + "day": 0, "start_time": 12, "end_time": 15 }, { - "week": 2, + "day": 2, "start_time": 210, "end_time": 213, "place": "" From 09431a29d33f4afcd2d1466c683252e9eaa9b5e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EA=B4=80=EA=B7=9C?= Date: Sun, 5 Jan 2025 18:38:18 +0900 Subject: [PATCH 61/61] =?UTF-8?q?chore:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/in/koreatech/koin/acceptance/LectureApiTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java b/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java index ebb500a414..5f72e18e34 100644 --- a/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java +++ b/src/test/java/in/koreatech/koin/acceptance/LectureApiTest.java @@ -61,12 +61,12 @@ void setup() { "is_elearning": "", "lecture_infos": [ { - "week": 0, + "day": 0, "start_time": 12, "end_time": 15 }, { - "week": 2, + "day": 2, "start_time": 210, "end_time": 213 }