-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat : 엑셀 파일 최신화 * feat : 리팩토링 진행 및 패키지 이동 * chore : 안 쓰는 import 제거 및 정리 * chore : 관규님 리뷰 반영 * chore : 개행 추가 * feat: lecture 컬럼 크기 수정 flyway 추가 (#1142) * fix: 식단 이미지 알림 롤백 (#1145) * fix: 스케줄러 cron식 수정 * fix: 식단 이미지 업로드 알림 롤백 * fix : 동계방학 생협 운영시간 업데이트 (#1144) * fix : 생협 동계학기 운영 시간 수정 * fix : 생협 동계학기 운영 시간 수정 * chore : 공백 추가 * fix: 세탁소 전화번호 수정 * feat: 스웨거 그룹화 (#1138) * chore: swagger 패키지 생성 및 클래스 이동 * feat: 비즈니스팀 API 그룹화 * chore: 비즈니스 API 추가 * feat: 캠퍼스팀 API 그룹화 * feat: 유저팀 API 그룹화 * feat: ABTEST API 그룹화 * feat: BCSD API 그룹화 * chore: 비즈니스팀 API 추가 * feat: 어드민 API 그룹화 * chore: 유저팀 API 추가 * feat: 로그인 API 그룹화 및 그룹 이름 변경 * refactor: 패키지 경로 enum화 * refactor: 중복 코드 메소드화 * refactor: 그룹 스웨거 파일 분할 * chore: 미사용 import 삭제 * chore: 메소드 명 변경 * chore: 리뷰 반영 * fix: 안경점, 우편취급국 운영시간 추가, 대즐 운영시간 오타 수정 (#1151) * feat: flyway추가 & model 관련 추가 및 수정 * feat: 시간표 조회 API 이수 구분 반환 추가 (#1150) * feat: repository 추가 * feat: exception 추가 * feat: 이수 구분 반환값 추가 * feat: coursetype 반환값 추가 * test: 테스트 코드 수정 * chore: 리뷰 반영 * fix: department 중복 수정 * fix: department 조회 로직 변경 * rebase : 충돌 해결 * chore : 현수님 리뷰 반영 --------- Co-authored-by: 신관규 <[email protected]> Co-authored-by: 허준기 <[email protected]> Co-authored-by: Hwang HyeonSik <[email protected]> Co-authored-by: 김원경 <[email protected]>
- Loading branch information
1 parent
862775f
commit 03ad206
Showing
11 changed files
with
349 additions
and
1 deletion.
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
src/main/java/in/koreatech/koin/domain/graduation/controller/GraduationApi.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package in.koreatech.koin.domain.graduation.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.RequestParam; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
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) Graduation: 졸업학점 계산기", description = "졸업학점 계산기 정보를 관리한다") | ||
public interface GraduationApi { | ||
@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("/graduation/excel/upload") | ||
ResponseEntity<String> uploadStudentGradeExcelFile( | ||
@RequestParam(value = "file") MultipartFile file, | ||
@Auth(permit = {STUDENT}) Integer userId | ||
); | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/in/koreatech/koin/domain/graduation/controller/GraduationController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package in.koreatech.koin.domain.graduation.controller; | ||
|
||
import java.io.IOException; | ||
|
||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import in.koreatech.koin.domain.graduation.service.GraduationService; | ||
import in.koreatech.koin.domain.user.model.UserType; | ||
import in.koreatech.koin.global.auth.Auth; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
public class GraduationController implements GraduationApi { | ||
|
||
private final GraduationService graduationService; | ||
|
||
@PostMapping("/graduation/excel/upload") | ||
public ResponseEntity<String> uploadStudentGradeExcelFile( | ||
@RequestParam(value = "file") MultipartFile file, | ||
@Auth(permit = {UserType.STUDENT}) Integer userId | ||
) { | ||
try { | ||
graduationService.readStudentGradeExcelFile(file, userId); | ||
return ResponseEntity.ok("파일이 성공적으로 업로드되었습니다."); | ||
} catch (IOException e) { | ||
return ResponseEntity.badRequest().build(); | ||
} | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/in/koreatech/koin/domain/graduation/exception/ExcelFileCheckException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package in.koreatech.koin.domain.graduation.exception; | ||
|
||
import in.koreatech.koin.global.exception.DataNotFoundException; | ||
|
||
public class ExcelFileCheckException extends DataNotFoundException { | ||
private static final String DEFAULT_MESSAGE = "엑셀 파일 형식이 아닙니다."; | ||
|
||
public ExcelFileCheckException(String message) { | ||
super(message); | ||
} | ||
|
||
public ExcelFileCheckException(String message, String detail) { | ||
super(message, detail); | ||
} | ||
|
||
public static ExcelFileCheckException withDetail(String detail) { | ||
return new ExcelFileCheckException(DEFAULT_MESSAGE, detail); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/in/koreatech/koin/domain/graduation/exception/ExcelFileNotFoundException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package in.koreatech.koin.domain.graduation.exception; | ||
|
||
import in.koreatech.koin.global.exception.DataNotFoundException; | ||
|
||
public class ExcelFileNotFoundException extends DataNotFoundException { | ||
private static final String DEFAULT_MESSAGE = "엑셀 파일을 찾을 수 없습니다."; | ||
|
||
public ExcelFileNotFoundException(String message) { | ||
super(message); | ||
} | ||
|
||
public ExcelFileNotFoundException(String message, String detail) { | ||
super(message, detail); | ||
} | ||
|
||
public static ExcelFileNotFoundException withDetail(String detail) { | ||
return new ExcelFileNotFoundException(DEFAULT_MESSAGE, detail); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
src/main/java/in/koreatech/koin/domain/graduation/model/GradeExcelData.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package in.koreatech.koin.domain.graduation.model; | ||
|
||
import org.apache.poi.ss.usermodel.Cell; | ||
import org.apache.poi.ss.usermodel.Row; | ||
|
||
public record GradeExcelData( | ||
String year, | ||
String semester, | ||
String code, | ||
String classTitle, | ||
String lectureClass, | ||
String professor, | ||
String courseType, | ||
String credit, | ||
String grade, | ||
String retakeStatus | ||
) { | ||
public static GradeExcelData fromRow(Row row) { | ||
return new GradeExcelData( | ||
getCellValueAsString(row.getCell(1)), | ||
getCellValueAsString(row.getCell(2)), | ||
getCellValueAsString(row.getCell(4)), | ||
getCellValueAsString(row.getCell(5)), | ||
getCellValueAsString(row.getCell(6)), | ||
getCellValueAsString(row.getCell(7)), | ||
getCellValueAsString(row.getCell(8)), | ||
getCellValueAsString(row.getCell(9)), | ||
getCellValueAsString(row.getCell(10)), | ||
getCellValueAsString(row.getCell(11)) | ||
); | ||
} | ||
|
||
private static String getCellValueAsString(Cell cell) { | ||
if (cell == null) { | ||
return ""; | ||
} | ||
return switch (cell.getCellType()) { | ||
case STRING -> cell.getStringCellValue(); | ||
case NUMERIC -> String.valueOf((int)cell.getNumericCellValue()); | ||
default -> ""; | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
155 changes: 155 additions & 0 deletions
155
src/main/java/in/koreatech/koin/domain/graduation/service/GraduationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package in.koreatech.koin.domain.graduation.service; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.util.List; | ||
|
||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | ||
import org.apache.poi.ss.usermodel.Cell; | ||
import org.apache.poi.ss.usermodel.Row; | ||
import org.apache.poi.ss.usermodel.Sheet; | ||
import org.apache.poi.ss.usermodel.Workbook; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import in.koreatech.koin.domain.graduation.model.GradeExcelData; | ||
import in.koreatech.koin.domain.graduation.model.CourseType; | ||
import in.koreatech.koin.domain.graduation.repository.CourseTypeRepository; | ||
import in.koreatech.koin.domain.graduation.exception.ExcelFileCheckException; | ||
import in.koreatech.koin.domain.graduation.exception.ExcelFileNotFoundException; | ||
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.timetableV2.repository.LectureRepositoryV2; | ||
import in.koreatech.koin.domain.timetableV2.repository.SemesterRepositoryV2; | ||
import in.koreatech.koin.domain.timetableV2.repository.TimetableFrameRepositoryV2; | ||
import in.koreatech.koin.domain.timetableV2.repository.TimetableLectureRepositoryV2; | ||
import in.koreatech.koin.domain.user.model.User; | ||
import in.koreatech.koin.domain.user.repository.UserRepository; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
public class GraduationService { | ||
|
||
private static final String MIDDLE_TOTAL = "소 계"; | ||
private static final String TOTAL = "합 계"; | ||
private static final String RETAKE = "Y"; | ||
private static final String UNSATISFACTORY = "U"; | ||
|
||
private final CourseTypeRepository courseTypeRepository; | ||
private final UserRepository userRepository; | ||
private final SemesterRepositoryV2 semesterRepositoryV2; | ||
private final LectureRepositoryV2 lectureRepositoryV2; | ||
private final TimetableLectureRepositoryV2 timetableLectureRepositoryV2; | ||
private final TimetableFrameRepositoryV2 timetableFrameRepositoryV2; | ||
|
||
@Transactional | ||
public void readStudentGradeExcelFile(MultipartFile file, Integer userId) throws IOException { | ||
checkFiletype(file); | ||
|
||
try (InputStream inputStream = file.getInputStream(); | ||
Workbook workbook = new HSSFWorkbook(inputStream) | ||
) { | ||
Sheet sheet = workbook.getSheetAt(0); | ||
TimetableFrame graduationFrame = null; | ||
String currentSemester = "default"; | ||
|
||
for (Row row : sheet) { | ||
GradeExcelData data = extractExcelData(row); | ||
if (row.getRowNum() == 0 || skipRow(data)) { | ||
continue; | ||
} | ||
|
||
if (data.classTitle().equals(TOTAL)) { | ||
break; | ||
} | ||
|
||
String semester = getKoinSemester(data.semester(), data.year()); | ||
CourseType courseType = courseTypeRepository.findByName(data.courseType()).orElse(null); | ||
Lecture lecture = lectureRepositoryV2.findBySemesterAndCodeAndLectureClass(semester, | ||
data.code(), data.lectureClass()).orElse(null); | ||
|
||
if (!currentSemester.equals(semester)) { | ||
currentSemester = semester; | ||
graduationFrame = createFrameAboutExcel(userId, currentSemester); | ||
} | ||
|
||
TimetableLecture timetableLecture = TimetableLecture.builder() | ||
.classTitle(data.classTitle()) | ||
.classTime(lecture != null ? lecture.getClassTime() : null) | ||
.professor(data.professor()) | ||
.grades(data.credit()) | ||
.isDeleted(false) | ||
.lecture(lecture) | ||
.timetableFrame(graduationFrame) | ||
.courseType(courseType) | ||
.build(); | ||
|
||
timetableLectureRepositoryV2.save(timetableLecture); | ||
} | ||
} | ||
} | ||
|
||
private TimetableFrame createFrameAboutExcel(Integer userId, String semester) { | ||
User user = userRepository.getById(userId); | ||
Semester saveSemester = semesterRepositoryV2.getBySemester(semester); | ||
|
||
List<TimetableFrame> timetableFrameList = timetableFrameRepositoryV2.findAllByUserIdAndSemesterId | ||
(userId, saveSemester.getId()); | ||
for (TimetableFrame timetableFrame : timetableFrameList) { | ||
if (timetableFrame.isMain()) { | ||
timetableFrame.cancelMain(); | ||
} | ||
} | ||
TimetableFrame graduationFrame = TimetableFrame.builder() | ||
.user(user) | ||
.semester(saveSemester) | ||
.name("Graduation Frame") | ||
.isDeleted(false) | ||
.isMain(true) | ||
.build(); | ||
timetableFrameRepositoryV2.save(graduationFrame); | ||
|
||
return graduationFrame; | ||
} | ||
|
||
private GradeExcelData extractExcelData(Row row) { | ||
return GradeExcelData.fromRow(row); | ||
} | ||
|
||
private void checkFiletype(MultipartFile file) { | ||
if (file == null) { | ||
throw new ExcelFileNotFoundException("파일이 있는지 확인 해주세요."); | ||
} | ||
|
||
String fileName = file.getOriginalFilename(); | ||
int findDot = fileName.lastIndexOf("."); | ||
if (findDot == -1) { | ||
throw new ExcelFileNotFoundException("파일의 형식이 맞는지 확인 해주세요."); | ||
} | ||
|
||
String extension = fileName.substring(findDot + 1); | ||
if (!extension.equals("xls") && !extension.equals("xlsx")) { | ||
throw new ExcelFileCheckException("엑셀 파일인지 확인 해주세요."); | ||
} | ||
} | ||
|
||
private boolean skipRow(GradeExcelData gradeExcelData) { | ||
return gradeExcelData.classTitle().equals(MIDDLE_TOTAL) || | ||
gradeExcelData.retakeStatus().equals(RETAKE) || | ||
gradeExcelData.grade().equals(UNSATISFACTORY); | ||
} | ||
|
||
private String getKoinSemester(String semester, String year) { | ||
if (semester.equals("1") || semester.equals("2")) { | ||
return year + semester; | ||
} else if (semester.equals("동계")) { | ||
return year + "-" + "겨울"; | ||
} else | ||
return year + "-" + "여름"; | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
src/main/java/in/koreatech/koin/domain/timetableV2/exception/ExcelFileCheckException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package in.koreatech.koin.domain.timetableV2.exception; | ||
|
||
import in.koreatech.koin.global.exception.DataNotFoundException; | ||
|
||
public class ExcelFileCheckException extends DataNotFoundException | ||
{ | ||
private static final String DEFAULT_MESSAGE = "엑셀 파일 형식이 아닙니다."; | ||
|
||
public ExcelFileCheckException(String message) { | ||
super(message); | ||
} | ||
|
||
public ExcelFileCheckException(String message, String detail) { | ||
super(message, detail); | ||
} | ||
|
||
public static ExcelFileCheckException withDetail(String detail) { | ||
return new ExcelFileCheckException(DEFAULT_MESSAGE, detail); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/in/koreatech/koin/domain/timetableV2/exception/ExcelFileNotFoundException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package in.koreatech.koin.domain.timetableV2.exception; | ||
|
||
import in.koreatech.koin.global.exception.DataNotFoundException; | ||
|
||
public class ExcelFileNotFoundException extends DataNotFoundException { | ||
private static final String DEFAULT_MESSAGE = "엑셀 파일을 찾을 수 없습니다."; | ||
|
||
public ExcelFileNotFoundException(String message) { | ||
super(message); | ||
} | ||
|
||
public ExcelFileNotFoundException(String message, String detail) { | ||
super(message, detail); | ||
} | ||
|
||
public static ExcelFileNotFoundException withDetail(String detail) { | ||
return new ExcelFileNotFoundException(DEFAULT_MESSAGE, detail); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 0 additions & 1 deletion
1
src/main/java/in/koreatech/koin/domain/timetableV2/model/TimetableLecture.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters