diff --git a/src/main/java/hackerthon/likelion13th/canfly/global/api/ErrorCode.java b/src/main/java/hackerthon/likelion13th/canfly/global/api/ErrorCode.java index f723b88..9d9b8ea 100644 --- a/src/main/java/hackerthon/likelion13th/canfly/global/api/ErrorCode.java +++ b/src/main/java/hackerthon/likelion13th/canfly/global/api/ErrorCode.java @@ -14,6 +14,7 @@ public enum ErrorCode implements BaseCode { // 실패 USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USER_4041", "존재하지 않는 회원입니다."), USER_NOT_FOUND_BY_EMAIL(HttpStatus.NOT_FOUND, "USER_4042", "EMAIL이 존재하지 않는 회원입니다."), USER_NOT_FOUND_BY_USERNAME(HttpStatus.NOT_FOUND, "USER_4043", "USERNAME이 존재하지 않는 회원입니다."), + INPUT_NOT_COMPLETED(HttpStatus.BAD_REQUEST, "COMMON_400", "프로필 구성에 필요한 정보들이 제공되지 않았습니다."), // Login WRONG_REFRESH_TOKEN(HttpStatus.NOT_FOUND, "JWT_4041", "일치하는 refresh token이 없습니다."), diff --git a/src/main/java/hackerthon/likelion13th/canfly/grades/controller/MockController.java b/src/main/java/hackerthon/likelion13th/canfly/grades/controller/MockController.java index d6c5c7b..6c41960 100644 --- a/src/main/java/hackerthon/likelion13th/canfly/grades/controller/MockController.java +++ b/src/main/java/hackerthon/likelion13th/canfly/grades/controller/MockController.java @@ -1,13 +1,10 @@ package hackerthon.likelion13th.canfly.grades.controller; -import hackerthon.likelion13th.canfly.domain.mock.Mock; -import hackerthon.likelion13th.canfly.domain.mock.MockScore; import hackerthon.likelion13th.canfly.domain.user.User; import hackerthon.likelion13th.canfly.global.api.ApiResponse; import hackerthon.likelion13th.canfly.global.api.SuccessCode; import hackerthon.likelion13th.canfly.grades.dto.MockCreateRequest; import hackerthon.likelion13th.canfly.grades.dto.MockCreateResponse; -import hackerthon.likelion13th.canfly.grades.dto.MockRequestDto; import hackerthon.likelion13th.canfly.grades.dto.MockResponseDto; import hackerthon.likelion13th.canfly.grades.service.MockService; import hackerthon.likelion13th.canfly.login.auth.mapper.CustomUserDetails; @@ -32,21 +29,26 @@ public class MockController { private final MockService mockService; private final UserService userService; - - @PostMapping - @Operation(summary = "모의고사 등록", description = "특정 년도, 월에 진행한 특정 학년의 모의고사를 등록하는 메서드입니다.") + // GPT + @PostMapping("/excel") + @Operation( + summary = "모의고사 등록(엑셀 평가)", + description = "엑셀 수식으로 각 과목의 백분위/등급/누적(%)를 계산한 뒤 저장합니다. " + + "규칙: 수학 3택1, (과탐/사탐) 합산 최대 2, 제2외국어 최대 1. " + + "표준점수 과목에서 계산 결과가 (백분위=0, 등급=0, 누적=0)이면 입력 오류로 처리됩니다." + ) @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Mock_2011", description = "모의고사 등록이 완료되었습니다."), }) - public ApiResponse createMock( + public ApiResponse createMockByExcel( @AuthenticationPrincipal CustomUserDetails customUserDetails, - @RequestBody MockRequestDto mockRequestDto) { - + @RequestBody MockCreateRequest req + ) { User user = userService.findUserByProviderId(customUserDetails.getUsername()); - MockResponseDto dto = mockService.createMock(user.getUid(), mockRequestDto); - return ApiResponse.onSuccess(SuccessCode.MOCK_CREATE_SUCCESS, dto); + MockCreateResponse res = mockService.createMockByExcel(user.getUid(), req); + return ApiResponse.onSuccess(SuccessCode.MOCK_CREATE_SUCCESS, res); } @GetMapping @@ -61,7 +63,6 @@ public ApiResponse> getAllMocksOfUser(@AuthenticationPrinc List allMocks = mockService.getAllMocksByUserId(user.getUid()); return ApiResponse.onSuccess(SuccessCode.MOCK_GET_ALL_SUCCESS, allMocks); - } @GetMapping("/{mockId}") @@ -69,8 +70,9 @@ public ApiResponse> getAllMocksOfUser(@AuthenticationPrinc @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Mock_2002", description = "모의고사 조회가 완료되었습니다."), }) - public ApiResponse getMockById(@PathVariable Long mockId) { - MockResponseDto responseDto = mockService.getMockById(mockId); + public ApiResponse getMockById(@PathVariable Long mockId, @AuthenticationPrincipal CustomUserDetails customUserDetails) { + User user = userService.findUserByProviderId(customUserDetails.getUsername()); + MockResponseDto responseDto = mockService.getMockById(mockId, user.getUid()); return ApiResponse.onSuccess(SuccessCode.MOCK_GET_SUCCESS, responseDto); } @@ -79,67 +81,39 @@ public ApiResponse getMockById(@PathVariable Long mockId) { @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Mockscore_2003", description = "과목 성적 조회가 완료되었습니다."), }) - public ApiResponse getMockScore(@PathVariable Long mockId, @PathVariable Long mockScoreId) { - MockResponseDto.MockScoreResponseDto mockScore = mockService.getMockScoreById(mockId, mockScoreId); + public ApiResponse getMockScore(@PathVariable Long mockId, + @PathVariable Long mockScoreId, + @AuthenticationPrincipal CustomUserDetails customUserDetails) { + User user = userService.findUserByProviderId(customUserDetails.getUsername()); + MockResponseDto.MockScoreResponseDto mockScore = mockService.getMockScoreById(mockId, mockScoreId, user.getUid()); return ApiResponse.onSuccess(SuccessCode.MOCKSCORE_GET_SUCCESS, mockScore); } -// 뭔가 만들면서 이상해져서 수정할 건데, 일단 이걸로 POST+DELETE를 해야 함 -// @Operation(summary = "모의고사 성적 수정", description = "특정 모의고사의 성적을 수정하는 메서드입니다.") -// @ApiResponses({ -// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Mock_2013", description = "특정 모의고사 정보 수정이 완료되었습니다."), -// }) -// public ApiResponse updateMockScore(@AuthenticationPrincipal CustomUserDetails userDetails, @PathVariable Long mockId, @RequestBody MockRequestDto mockRequestDto) { -// User user = userService.findUserByProviderId(userDetails.getUsername()); -// Mock updatedMock = new Mock(); -// if (mockRequestDto.getScoreLists() != null && !mockRequestDto.getScoreLists().isEmpty()) { -// List newScores = mockRequestDto.getScoreLists(); -// for (MockRequestDto.MockScoreRequestDto scoreDto : newScores) { -// MockScore mockScore = MockScore.builder() -// .standardScore(scoreDto.getStandardScore()) -// .percentile(scoreDto.getPercentile()) -// .grade(scoreDto.getGrade()) -// .cumulative(scoreDto.getCumulative()) -// .category(scoreDto.getCategory()) -// .name(scoreDto.getName()) -// .build(); -// updatedMock.addMockScore(mockScore); -// } -// } -// MockResponseDto responseDto = new MockResponseDto(updatedMock); -// return ApiResponse.onSuccess(SuccessCode.MOCKSCORE_PUT_SUCCESS, responseDto); -// } - @DeleteMapping("/{mockId}") @Operation(summary = "모의고사 삭제", description = "특정 모의고사를 삭제하는 메서드입니다.") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Mock_2004", description = "모의고사 삭제가 완료되었습니다."), }) - public ApiResponse deleteMock(@PathVariable Long mockId) { - mockService.deleteMock(mockId); + public ApiResponse deleteMock(@PathVariable Long mockId, @AuthenticationPrincipal CustomUserDetails customUserDetails) { + User user = userService.findUserByProviderId(customUserDetails.getUsername()); + mockService.deleteMock(mockId, user.getUid()); return ApiResponse.onSuccess(SuccessCode.MOCK_DELETE_SUCCESS, true); } - // GPT - @PostMapping("/excel") - @Operation( - summary = "모의고사 등록(엑셀 평가)", - description = "엑셀 수식으로 각 과목의 백분위/등급/누적(%)를 계산한 뒤 저장합니다. " + - "규칙: 수학 3택1, (과탐/사탐) 합산 최대 2, 제2외국어 최대 1. " + - "표준점수 과목에서 계산 결과가 (백분위=0, 등급=0, 누적=0)이면 입력 오류로 처리됩니다." - ) - @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Mock_2011", description = "모의고사 등록이 완료되었습니다."), - }) - public ApiResponse createMockByExcel( - @AuthenticationPrincipal CustomUserDetails customUserDetails, - @RequestBody MockCreateRequest req - ) { - User user = userService.findUserByProviderId(customUserDetails.getUsername()); - - MockCreateResponse res = mockService.createMockByExcel(user.getUid(), req); - - return ApiResponse.onSuccess(SuccessCode.MOCK_CREATE_SUCCESS, res); - } + // @PostMapping +// @Operation(summary = "모의고사 등록", description = "특정 년도, 월에 진행한 특정 학년의 모의고사를 등록하는 메서드입니다.") +// @ApiResponses({ +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Mock_2011", description = "모의고사 등록이 완료되었습니다."), +// }) +// public ApiResponse createMock( +// @AuthenticationPrincipal CustomUserDetails customUserDetails, +// @RequestBody MockRequestDto mockRequestDto) { +// +// User user = userService.findUserByProviderId(customUserDetails.getUsername()); +// MockResponseDto dto = mockService.createMock(user.getUid(), mockRequestDto); +// +// return ApiResponse.onSuccess(SuccessCode.MOCK_CREATE_SUCCESS, dto); +// +// } } diff --git a/src/main/java/hackerthon/likelion13th/canfly/grades/controller/ReportController.java b/src/main/java/hackerthon/likelion13th/canfly/grades/controller/ReportController.java index a807e8e..f634da9 100644 --- a/src/main/java/hackerthon/likelion13th/canfly/grades/controller/ReportController.java +++ b/src/main/java/hackerthon/likelion13th/canfly/grades/controller/ReportController.java @@ -37,27 +37,11 @@ public ApiResponse createReport( @AuthenticationPrincipal CustomUserDetails customUserDetails, @RequestBody ReportRequestDto reportRequestDto) { - User user = userService.findUserByProviderId(customUserDetails.getUsername()); - ReportResponseDto responseDto = reportService.createReport(user.getUid(), reportRequestDto); return ApiResponse.onSuccess(SuccessCode.REPORT_CREATE_SUCCESS, responseDto); } -// @PostMapping("/{reportId}") -// @Operation(summary = "내신 점수 등록", description = "어떤 내신의 특정 과목 성적을 입력하는 메서드입니다..") -// @ApiResponses({ -// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Report_2012", description = "내신 성적 등록이 완료되었습니다."), -// }) -// public ApiResponse createReportScoreLists( -// @PathVariable Long reportId, -// @RequestBody ReportRequestDto.ReportScoreRequestDto reportScoreRequestDto -// ) { -// -// ReportResponseDto responseDto = reportService.addReportScoreToReport(reportId, reportScoreRequestDto); -// return ApiResponse.onSuccess(SuccessCode.REPORTSCORE_CREATE_SUCCESS, responseDto); -// } - @GetMapping @Operation(summary = "전체 내신 조회", description = "사용자가 진행했던 모든 내신를 조회하는 메서드입니다.") @ApiResponses({ @@ -74,8 +58,10 @@ public ApiResponse> getAllReportsOfUser(@AuthenticationP @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Report_2002", description = "내신 조회가 완료되었습니다."), }) - public ApiResponse getReportById(@PathVariable Long reportId) { - ReportResponseDto responseDto = reportService.getReportById(reportId); + public ApiResponse getReportById(@PathVariable Long reportId, + @AuthenticationPrincipal CustomUserDetails customUserDetails) { + User user = userService.findUserByProviderId(customUserDetails.getUsername()); + ReportResponseDto responseDto = reportService.getReportById(reportId, user.getUid()); return ApiResponse.onSuccess(SuccessCode.REPORT_GET_SUCCESS, responseDto); } @@ -84,40 +70,57 @@ public ApiResponse getReportById(@PathVariable Long reportId) @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Report_2003", description = "과목 성적 조회가 완료되었습니다."), }) - public ApiResponse getReportScore(@PathVariable Long reportId, @PathVariable Long reportScoreId) { - ReportResponseDto.ReportScoreResponseDto reportScore = reportService.getReportScoreById(reportId, reportScoreId); + public ApiResponse getReportScore(@PathVariable Long reportId, + @PathVariable Long reportScoreId, + @AuthenticationPrincipal CustomUserDetails customUserDetails) { + User user = userService.findUserByProviderId(customUserDetails.getUsername()); + ReportResponseDto.ReportScoreResponseDto reportScore = reportService.getReportScoreById(reportId, reportScoreId, user.getUid()); return ApiResponse.onSuccess(SuccessCode.REPORTSCORE_GET_SUCCESS, reportScore); } - @PutMapping("/{reportId}") - @Operation(summary = "내신 정보 수정", description = "특정 내신의 정보를 수정하는 메서드입니다.") //※ 규칙: 여기에서 절대로 CategoryName은 건들면 안됨 - @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Report_2013", description = "특정 내신 정보 수정이 완료되었습니다."), - }) - public ApiResponse updateReport(@PathVariable Long reportId, @RequestBody ReportRequestDto reportRequestDto) { - ReportResponseDto responseDto = reportService.updateReport(reportId, reportRequestDto); - return ApiResponse.onSuccess(SuccessCode.REPORT_PUT_SUCCESS, responseDto); - } - - @PutMapping("/{reportId}/{reportScoreId}") - @Operation(summary = "내신 성적 수정", description = "특정 내신의 성적을 수정하는 메서드입니다.") - @ApiResponses({ - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Report_2014", description = "내신 성적 수정이 완료되었습니다."), - }) - public ApiResponse updateReportScore(@PathVariable Long reportId, @PathVariable Long reportScoreId, @RequestBody ReportRequestDto.ReportScoreRequestDto reportScoreRequestDto) { - ReportResponseDto.ReportScoreResponseDto responseDto = reportService.updateReportScore(reportScoreId, reportScoreRequestDto); - return ApiResponse.onSuccess(SuccessCode.REPORTSCORE_PUT_SUCCESS, responseDto); - } - @DeleteMapping("/{reportId}") @Operation(summary = "내신 삭제", description = "특정 내신를 삭제하는 메서드입니다.") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Report_2004", description = "내신 삭제가 완료되었습니다."), }) - public ApiResponse deleteReport(@PathVariable Long reportId) { - reportService.deleteReport(reportId); + public ApiResponse deleteReport(@PathVariable Long reportId, @AuthenticationPrincipal CustomUserDetails customUserDetails) { + User user = userService.findUserByProviderId(customUserDetails.getUsername()); + reportService.deleteReport(reportId, user.getUid()); return ApiResponse.onSuccess(SuccessCode.REPORT_DELETE_SUCCESS, true); } + // @PostMapping("/{reportId}") +// @Operation(summary = "내신 점수 등록", description = "어떤 내신의 특정 과목 성적을 입력하는 메서드입니다..") +// @ApiResponses({ +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Report_2012", description = "내신 성적 등록이 완료되었습니다."), +// }) +// public ApiResponse createReportScoreLists( +// @PathVariable Long reportId, +// @RequestBody ReportRequestDto.ReportScoreRequestDto reportScoreRequestDto +// ) { +// +// ReportResponseDto responseDto = reportService.addReportScoreToReport(reportId, reportScoreRequestDto); +// return ApiResponse.onSuccess(SuccessCode.REPORTSCORE_CREATE_SUCCESS, responseDto); +// } + + // @PutMapping("/{reportId}") +// @Operation(summary = "내신 정보 수정", description = "특정 내신의 정보를 수정하는 메서드입니다.") //※ 규칙: 여기에서 절대로 CategoryName은 건들면 안됨 +// @ApiResponses({ +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Report_2013", description = "특정 내신 정보 수정이 완료되었습니다."), +// }) +// public ApiResponse updateReport(@PathVariable Long reportId, @RequestBody ReportRequestDto reportRequestDto) { +// ReportResponseDto responseDto = reportService.updateReport(reportId, reportRequestDto); +// return ApiResponse.onSuccess(SuccessCode.REPORT_PUT_SUCCESS, responseDto); +// } +// +// @PutMapping("/{reportId}/{reportScoreId}") +// @Operation(summary = "내신 성적 수정", description = "특정 내신의 성적을 수정하는 메서드입니다.") +// @ApiResponses({ +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "Report_2014", description = "내신 성적 수정이 완료되었습니다."), +// }) +// public ApiResponse updateReportScore(@PathVariable Long reportId, @PathVariable Long reportScoreId, @RequestBody ReportRequestDto.ReportScoreRequestDto reportScoreRequestDto) { +// ReportResponseDto.ReportScoreResponseDto responseDto = reportService.updateReportScore(reportScoreId, reportScoreRequestDto); +// return ApiResponse.onSuccess(SuccessCode.REPORTSCORE_PUT_SUCCESS, responseDto); +// } } diff --git a/src/main/java/hackerthon/likelion13th/canfly/grades/dto/ReportRequestDto.java b/src/main/java/hackerthon/likelion13th/canfly/grades/dto/ReportRequestDto.java index 5824cd9..07b0e4e 100644 --- a/src/main/java/hackerthon/likelion13th/canfly/grades/dto/ReportRequestDto.java +++ b/src/main/java/hackerthon/likelion13th/canfly/grades/dto/ReportRequestDto.java @@ -14,7 +14,6 @@ public class ReportRequestDto { private Integer userGrade; private Integer term; private Integer categoryName; - private BigDecimal categoryGrade; private List scoreLists; @Getter diff --git a/src/main/java/hackerthon/likelion13th/canfly/grades/repository/MockRepository.java b/src/main/java/hackerthon/likelion13th/canfly/grades/repository/MockRepository.java index ba6f4d5..438bf4d 100644 --- a/src/main/java/hackerthon/likelion13th/canfly/grades/repository/MockRepository.java +++ b/src/main/java/hackerthon/likelion13th/canfly/grades/repository/MockRepository.java @@ -15,4 +15,8 @@ public interface MockRepository extends JpaRepository { Optional findByUserUidAndExamYearAndExamMonthAndExamGrade( String uid, Integer examYear, Integer examMonth, Integer examGrade ); + + Optional findByIdAndUser_Uid(Long mockId, String userId); + + void deleteByIdAndUser_Uid(Long id, String userUid); } diff --git a/src/main/java/hackerthon/likelion13th/canfly/grades/repository/ReportRepository.java b/src/main/java/hackerthon/likelion13th/canfly/grades/repository/ReportRepository.java index 3d4a3a5..3f5e941 100644 --- a/src/main/java/hackerthon/likelion13th/canfly/grades/repository/ReportRepository.java +++ b/src/main/java/hackerthon/likelion13th/canfly/grades/repository/ReportRepository.java @@ -5,9 +5,18 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; +import java.util.Optional; public interface ReportRepository extends JpaRepository { List findByUser(User user); + + Optional findByUserAndUserGradeAndTermAndCategoryName( + User user, Integer userGrade, Integer term, Integer categoryName + ); + + Optional findByIdAndUser_Uid(Long reportId, String userId); + + void deleteByIdAndUser_Uid(Long reportId, String userId); } diff --git a/src/main/java/hackerthon/likelion13th/canfly/grades/service/MockService.java b/src/main/java/hackerthon/likelion13th/canfly/grades/service/MockService.java index ceb7f2d..67ec626 100644 --- a/src/main/java/hackerthon/likelion13th/canfly/grades/service/MockService.java +++ b/src/main/java/hackerthon/likelion13th/canfly/grades/service/MockService.java @@ -4,14 +4,10 @@ import hackerthon.likelion13th.canfly.domain.mock.Mock; import hackerthon.likelion13th.canfly.domain.mock.MockScore; import hackerthon.likelion13th.canfly.domain.user.User; -import hackerthon.likelion13th.canfly.global.api.ErrorCode; -import hackerthon.likelion13th.canfly.global.exception.GeneralException; import hackerthon.likelion13th.canfly.grades.dto.MockCreateRequest; import hackerthon.likelion13th.canfly.grades.dto.MockCreateResponse; -import hackerthon.likelion13th.canfly.grades.dto.MockRequestDto; import hackerthon.likelion13th.canfly.grades.dto.MockResponseDto; import hackerthon.likelion13th.canfly.grades.repository.MockRepository; -import hackerthon.likelion13th.canfly.grades.repository.MockScoreRepository; import hackerthon.likelion13th.canfly.login.repository.UserRepository; import hackerthon.likelion13th.canfly.score.ScoreExcelEngine; import hackerthon.likelion13th.canfly.score.SubjectCategoryMapper; @@ -25,7 +21,6 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; @@ -34,66 +29,14 @@ @RequiredArgsConstructor public class MockService { private final MockRepository mockRepository; - private final MockScoreRepository mockScoreRepository; private final UserRepository userRepository; private final SubjectSelectionValidator selectionValidator; private final ScoreExcelEngine excelEngine; - @Transactional - public MockResponseDto createMock(String userId, MockRequestDto mockRequestDto) { - User user = userRepository.findByUid(userId) - .orElseThrow(() -> GeneralException.of(ErrorCode.USER_NOT_FOUND)); - - Mock newMock = Mock.builder() - .examYear(mockRequestDto.getExamYear()) - .examMonth(mockRequestDto.getExamMonth()) - .examGrade(mockRequestDto.getExamGrade()) - .user(user) - .build(); - - // MockScoreRequestDto 리스트를 MockScore 엔티티 리스트로 변환하여 추가 - if (mockRequestDto.getScoreLists() != null && !mockRequestDto.getScoreLists().isEmpty()) { - for (MockRequestDto.MockScoreRequestDto scoreDto : mockRequestDto.getScoreLists()) { - MockScore mockScore = MockScore.builder() - .standardScore(scoreDto.getStandardScore()) - .percentile(scoreDto.getPercentile()) - .grade(scoreDto.getGrade()) - .cumulative(scoreDto.getCumulative()) - .category(scoreDto.getCategory()) - .name(scoreDto.getName()) - .build(); - newMock.addMockScore(mockScore); - } - } - user.addMock(newMock); - mockRepository.save(newMock); - - return new MockResponseDto(newMock); - } -// 사용하지 않는 관계로 주석 처리 -// @Transactional -// public MockResponseDto addMockScoreToMock(Long mockId, MockRequestDto.MockScoreRequestDto scoreRequestDto) { -// Mock mock = mockRepository.findById(mockId) -// .orElseThrow(() -> new IllegalArgumentException("Mock not found with id: " + mockId)); -// -// // DTO 필드에서 MockScore 엔티티 직접 생성 -// MockScore newMockScore = MockScore.builder() -// .standardScore(scoreRequestDto.getStandardScore()) -// .percentile(scoreRequestDto.getPercentile()) -// .grade(scoreRequestDto.getGrade()) -// .cumulative(scoreRequestDto.getCumulative()) -// .category(scoreRequestDto.getCategory()) -// .name(scoreRequestDto.getName()) -// .build(); -// mock.addMockScore(newMockScore); // Mock 엔티티에 MockScore 추가 (양방향 관계 설정) -// mockScoreRepository.save(newMockScore); -// return new MockResponseDto(mock); -// } - @Transactional(readOnly = true) - public MockResponseDto getMockById(Long mockId) { - Mock mock = mockRepository.findById(mockId) + public MockResponseDto getMockById(Long mockId, String userId) { + Mock mock = mockRepository.findByIdAndUser_Uid(mockId, userId) .orElseThrow(() -> new IllegalArgumentException("Mock not found with ID: " + mockId)); return new MockResponseDto(mock); } @@ -112,9 +55,9 @@ public List getAllMocksByUserId(String userId) { } @Transactional - public MockResponseDto.MockScoreResponseDto getMockScoreById(Long mockId, Long scoreId) { - Mock mock = mockRepository.findById(mockId) - .orElseThrow(() -> new IllegalArgumentException("Mock not found with id: " + mockId)); + public MockResponseDto.MockScoreResponseDto getMockScoreById(Long mockId, Long scoreId, String userId) { + Mock mock = mockRepository.findByIdAndUser_Uid(mockId, userId) + .orElseThrow(() -> new IllegalArgumentException("Mock for user not found with id: " + mockId)); MockScore mockScore = mock.getScoreLists().stream() .filter(score -> score.getId().equals(scoreId)) @@ -125,38 +68,8 @@ public MockResponseDto.MockScoreResponseDto getMockScoreById(Long mockId, Long s } @Transactional - public MockResponseDto.MockScoreResponseDto updateMockScore(Long mockScoreId, MockRequestDto.MockScoreRequestDto scoreRequestDto) { - MockScore existingMockScore = mockScoreRepository.findById(mockScoreId) - .orElseThrow(() -> new IllegalArgumentException("MockScore not found with id: " + mockScoreId)); - existingMockScore.setStandardScore(scoreRequestDto.getStandardScore()); - existingMockScore.setPercentile(scoreRequestDto.getPercentile()); - existingMockScore.setGrade(scoreRequestDto.getGrade()); - existingMockScore.setCumulative(scoreRequestDto.getCumulative()); - existingMockScore.setCategory(scoreRequestDto.getCategory()); - existingMockScore.setName(scoreRequestDto.getName()); - MockScore updatedMockScore = mockScoreRepository.save(existingMockScore); - return convertToDto(updatedMockScore); - } - -// if (mockRequestDto.getScoreLists() != null && !mockRequestDto.getScoreLists().isEmpty()) { -// for (MockRequestDto.MockScoreRequestDto scoreDto : mockRequestDto.getScoreLists()) { -// MockScore mockScore = MockScore.builder() -// .standardScore(scoreDto.getStandardScore()) -// .percentile(scoreDto.getPercentile()) -// .grade(scoreDto.getGrade()) -// .cumulative(scoreDto.getCumulative()) -// .category(scoreDto.getCategory()) -// .name(scoreDto.getName()) -// .build(); -// newMock.addMockScore(mockScore); -// } -// } -// user.addMock(newMock); -// mockRepository.save(newMock); - - @Transactional - public void deleteMock(Long mockId) { - mockRepository.deleteById(mockId); + public void deleteMock(Long mockId, String userId) { + mockRepository.deleteByIdAndUser_Uid(mockId, userId); } private MockResponseDto convertToDto(Mock mock) { @@ -286,4 +199,100 @@ private Integer toInt(Object v) { private BigDecimal scale2(BigDecimal v) { return (v == null) ? null : v.setScale(2, java.math.RoundingMode.HALF_UP); } + + +// @Transactional +// public MockResponseDto createMock(String userId, MockRequestDto mockRequestDto) { +// User user = userRepository.findById(userId) +// .orElseThrow(() -> GeneralException.of(ErrorCode.USER_NOT_FOUND)); +// +// Optional existingMockOpt = mockRepository.findByUserUidAndExamYearAndExamMonthAndExamGrade( +// user.getUid(), +// mockRequestDto.getExamYear(), +// mockRequestDto.getExamMonth(), +// mockRequestDto.getExamGrade() +// ); +// +// Mock updateMock = null; +// if (existingMockOpt.isPresent()) { +// // Mock 존재 시에는 수정 +// updateMock = existingMockOpt.get(); +// updateMock.getScoreLists().clear(); +// +// } else { +// // Mock 없으면 생성 +// updateMock = Mock.builder() +// .user(user) +// .examYear(mockRequestDto.getExamYear()) +// .examMonth(mockRequestDto.getExamMonth()) +// .examGrade(mockRequestDto.getExamGrade()) +// .build(); +// user.addMock(updateMock); +// } +// +// // MockScoreRequestDto 리스트를 MockScore 엔티티 리스트로 변환하여 추가 +// if (mockRequestDto.getScoreLists() != null && !mockRequestDto.getScoreLists().isEmpty()) { +// for (MockRequestDto.MockScoreRequestDto scoreDto : mockRequestDto.getScoreLists()) { +// MockScore mockScore = MockScore.builder() +// .standardScore(scoreDto.getStandardScore()) +// .percentile(scoreDto.getPercentile()) +// .grade(scoreDto.getGrade()) +// .cumulative(scoreDto.getCumulative()) +// .category(scoreDto.getCategory()) +// .name(scoreDto.getName()) +// .build(); +// updateMock.addMockScore(mockScore); +// } +// } +// Mock updatedMock = mockRepository.save(updateMock); +// return new MockResponseDto(updatedMock); +// } +// 사용하지 않는 관계로 주석 처리 +// @Transactional +// public MockResponseDto addMockScoreToMock(Long mockId, MockRequestDto.MockScoreRequestDto scoreRequestDto) { +// Mock mock = mockRepository.findById(mockId) +// .orElseThrow(() -> new IllegalArgumentException("Mock not found with id: " + mockId)); +// +// // DTO 필드에서 MockScore 엔티티 직접 생성 +// MockScore newMockScore = MockScore.builder() +// .standardScore(scoreRequestDto.getStandardScore()) +// .percentile(scoreRequestDto.getPercentile()) +// .grade(scoreRequestDto.getGrade()) +// .cumulative(scoreRequestDto.getCumulative()) +// .category(scoreRequestDto.getCategory()) +// .name(scoreRequestDto.getName()) +// .build(); +// mock.addMockScore(newMockScore); // Mock 엔티티에 MockScore 추가 (양방향 관계 설정) +// mockScoreRepository.save(newMockScore); +// return new MockResponseDto(mock); +// } + // @Transactional +// public MockResponseDto.MockScoreResponseDto updateMockScore(Long mockScoreId, MockRequestDto.MockScoreRequestDto scoreRequestDto) { +// MockScore existingMockScore = mockScoreRepository.findById(mockScoreId) +// .orElseThrow(() -> new IllegalArgumentException("MockScore not found with id: " + mockScoreId)); +// existingMockScore.setStandardScore(scoreRequestDto.getStandardScore()); +// existingMockScore.setPercentile(scoreRequestDto.getPercentile()); +// existingMockScore.setGrade(scoreRequestDto.getGrade()); +// existingMockScore.setCumulative(scoreRequestDto.getCumulative()); +// existingMockScore.setCategory(scoreRequestDto.getCategory()); +// existingMockScore.setName(scoreRequestDto.getName()); +// MockScore updatedMockScore = mockScoreRepository.save(existingMockScore); +// return convertToDto(updatedMockScore); +// } + +// if (mockRequestDto.getScoreLists() != null && !mockRequestDto.getScoreLists().isEmpty()) { +// for (MockRequestDto.MockScoreRequestDto scoreDto : mockRequestDto.getScoreLists()) { +// MockScore mockScore = MockScore.builder() +// .standardScore(scoreDto.getStandardScore()) +// .percentile(scoreDto.getPercentile()) +// .grade(scoreDto.getGrade()) +// .cumulative(scoreDto.getCumulative()) +// .category(scoreDto.getCategory()) +// .name(scoreDto.getName()) +// .build(); +// newMock.addMockScore(mockScore); +// } +// } +// user.addMock(newMock); +// mockRepository.save(newMock); } \ No newline at end of file diff --git a/src/main/java/hackerthon/likelion13th/canfly/grades/service/ReportService.java b/src/main/java/hackerthon/likelion13th/canfly/grades/service/ReportService.java index d5c98f9..37c4bd8 100644 --- a/src/main/java/hackerthon/likelion13th/canfly/grades/service/ReportService.java +++ b/src/main/java/hackerthon/likelion13th/canfly/grades/service/ReportService.java @@ -18,6 +18,7 @@ import java.math.MathContext; import java.math.RoundingMode; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @@ -30,17 +31,34 @@ public class ReportService { private final UserRepository userRepository; @Transactional - public ReportResponseDto createReport(String userId, ReportRequestDto reportRequestDto) { - User user = userRepository.findByUid(userId) - .orElseThrow(() -> new IllegalArgumentException("User not found with name: " + userId)); - - Report newReport = Report.builder() - .categoryName(reportRequestDto.getCategoryName()) - .categoryGrade(BigDecimal.valueOf(0.0)) - .term(reportRequestDto.getTerm()) - .userGrade(reportRequestDto.getUserGrade()) - .user(user) - .build(); + public ReportResponseDto createReport(String uid, ReportRequestDto reportRequestDto) { + User user = userRepository.findByUid(uid) + .orElseThrow(() -> new IllegalArgumentException("User not found with id: " + uid)); + + Optional existingReportOpt = reportRepository.findByUserAndUserGradeAndTermAndCategoryName( + user, + reportRequestDto.getUserGrade(), + reportRequestDto.getTerm(), + reportRequestDto.getCategoryName() + ); + + Report updateReport = null; + if (existingReportOpt.isPresent()) { + // Report 존재 시에는 수정 + updateReport = existingReportOpt.get(); + updateReport.getScoreLists().clear(); + + } else { + // Report 없으면 생성 + updateReport = Report.builder() + .user(user) + .userGrade(reportRequestDto.getUserGrade()) + .term(reportRequestDto.getTerm()) + .categoryName(reportRequestDto.getCategoryName()) + .build(); + user.addReport(updateReport); + } + // ReportScoreRequestDto 리스트를 ReportScore 엔티티 리스트로 변환하여 추가 if (reportRequestDto.getScoreLists() != null && !reportRequestDto.getScoreLists().isEmpty()) { @@ -55,42 +73,40 @@ public ReportResponseDto createReport(String userId, ReportRequestDto reportRequ .score(scoreDto.getScore()) .credit(scoreDto.getCredit()) .build(); - newReport.addReportScore(reportScore); + updateReport.addReportScore(reportScore); } } - newReport.setCategoryGrade(calculateAverageFromList(newReport.getScoreLists())); - - user.addReport(newReport); - reportRepository.save(newReport); - return new ReportResponseDto(newReport); + updateReport.setCategoryGrade(calculateAverageFromList(updateReport.getScoreLists())); + Report savedReport = reportRepository.save(updateReport); + return new ReportResponseDto(savedReport); } - @Transactional - public ReportResponseDto addReportScoreToReport(Long reportId, ReportRequestDto.ReportScoreRequestDto scoreRequestDto) { - Report report = reportRepository.findById(reportId) - .orElseThrow(() -> new IllegalArgumentException("Report not found with id: " + reportId)); - - // DTO 필드에서 ReportScore 엔티티 직접 생성 - ReportScore newReportScore = ReportScore.builder() - .subject(scoreRequestDto.getSubject()) - .grade(scoreRequestDto.getGrade()) - .achievement(scoreRequestDto.getAchievement()) - .studentNum(scoreRequestDto.getStudentNum()) - .standardDeviation(scoreRequestDto.getStandardDeviation()) - .subjectAverage(scoreRequestDto.getSubjectAverage()) - .score(scoreRequestDto.getScore()) - .credit(scoreRequestDto.getCredit()) - .build();; - report.addReportScore(newReportScore); // Report 엔티티에 ReportScore 추가 (양방향 관계 설정) - report.setCategoryGrade(calculateAverageFromList(report.getScoreLists())); - reportScoreRepository.save(newReportScore); - return new ReportResponseDto(report); - } +// @Transactional +// public ReportResponseDto addReportScoreToReport(Long reportId, ReportRequestDto.ReportScoreRequestDto scoreRequestDto) { +// Report report = reportRepository.findById(reportId) +// .orElseThrow(() -> new IllegalArgumentException("Report not found with id: " + reportId)); +// +// // DTO 필드에서 ReportScore 엔티티 직접 생성 +// ReportScore newReportScore = ReportScore.builder() +// .subject(scoreRequestDto.getSubject()) +// .grade(scoreRequestDto.getGrade()) +// .achievement(scoreRequestDto.getAchievement()) +// .studentNum(scoreRequestDto.getStudentNum()) +// .standardDeviation(scoreRequestDto.getStandardDeviation()) +// .subjectAverage(scoreRequestDto.getSubjectAverage()) +// .score(scoreRequestDto.getScore()) +// .credit(scoreRequestDto.getCredit()) +// .build();; +// report.addReportScore(newReportScore); // Report 엔티티에 ReportScore 추가 (양방향 관계 설정) +// report.setCategoryGrade(calculateAverageFromList(report.getScoreLists())); +// reportScoreRepository.save(newReportScore); +// return new ReportResponseDto(report); +// } @Transactional(readOnly = true) - public ReportResponseDto getReportById(Long reportId) { - Report report = reportRepository.findById(reportId) - .orElseThrow(() -> new IllegalArgumentException("Report not found with ID: " + reportId)); + public ReportResponseDto getReportById(Long reportId, String userId) { + Report report = reportRepository.findByIdAndUser_Uid(reportId, userId) + .orElseThrow(() -> new IllegalArgumentException("Report for user not found with ID: " + reportId)); return new ReportResponseDto(report); } @@ -108,9 +124,9 @@ public List getAllReportsByUserId(String userId) { } @Transactional - public ReportResponseDto.ReportScoreResponseDto getReportScoreById(Long reportId, Long scoreId) { - Report report = reportRepository.findById(reportId) - .orElseThrow(() -> new IllegalArgumentException("Report not found with id: " + reportId)); + public ReportResponseDto.ReportScoreResponseDto getReportScoreById(Long reportId, Long scoreId, String userId) { + Report report = reportRepository.findByIdAndUser_Uid(reportId, userId) + .orElseThrow(() -> new IllegalArgumentException("Report for user not found with id: " + reportId)); ReportScore reportScore = report.getScoreLists().stream() .filter(score -> score.getId().equals(scoreId)) @@ -124,56 +140,61 @@ private BigDecimal calculateAverageFromList(List scores) { if (scores == null || scores.isEmpty()) { return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); } - - BigDecimal sum = scores.stream() - .map(ReportScore::getGrade) - .map(BigDecimal::valueOf) + // 학점에 따른 등급 가중치 조정 + BigDecimal weightedSum = scores.stream() + .map(score -> { + BigDecimal grade = BigDecimal.valueOf(score.getGrade()); + BigDecimal credit = BigDecimal.valueOf(score.getCredit()); + return grade.multiply(credit); + }) .reduce(BigDecimal.ZERO, BigDecimal::add); - BigDecimal count = BigDecimal.valueOf(scores.size()); + BigDecimal totalCredits = scores.stream() + .map(score -> BigDecimal.valueOf(score.getCredit())) + .reduce(BigDecimal.ZERO, BigDecimal::add); - // 0으로 나누는 경우 방지 - if (count.compareTo(BigDecimal.ZERO) == 0) { + // 0으로 나누는 경우 방지 (총 학점이 0일 경우) + if (totalCredits.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP); } - BigDecimal average = sum.divide(count, MathContext.DECIMAL64); + BigDecimal average = weightedSum.divide(totalCredits, MathContext.DECIMAL64); return average.setScale(2, RoundingMode.HALF_UP); } - @Transactional - public ReportResponseDto updateReport(Long reportId, ReportRequestDto reportRequestDto) { - Report existingReport = reportRepository.findById(reportId) - .orElseThrow(() -> new IllegalArgumentException("Report not found with id: " + reportId)); - existingReport.setCategoryName(reportRequestDto.getCategoryName()); - Report updatedReport = reportRepository.save(existingReport); - return convertToDto(updatedReport); - } - - @Transactional - public ReportResponseDto.ReportScoreResponseDto updateReportScore(Long reportScoreId, ReportRequestDto.ReportScoreRequestDto scoreRequestDto) { - ReportScore existingReportScore = reportScoreRepository.findById(reportScoreId) - .orElseThrow(() -> new IllegalArgumentException("ReportScore not found with id: " + reportScoreId)); - existingReportScore.setSubject(scoreRequestDto.getSubject()); - existingReportScore.setGrade(scoreRequestDto.getGrade()); - existingReportScore.setAchievement(scoreRequestDto.getAchievement()); - existingReportScore.setStudentNum(scoreRequestDto.getStudentNum()); - existingReportScore.setStandardDeviation(scoreRequestDto.getStandardDeviation()); - existingReportScore.setSubjectAverage(scoreRequestDto.getSubjectAverage()); - existingReportScore.setScore(scoreRequestDto.getScore()); - existingReportScore.setCredit(scoreRequestDto.getCredit()); - Report parentReport = existingReportScore.getReport(); // ReportScore가 Report 참조를 가지고 있어야 함 - if (parentReport != null) { - parentReport.setCategoryGrade(calculateAverageFromList(parentReport.getScoreLists())); - } - ReportScore updatedReportScore = reportScoreRepository.save(existingReportScore); - return convertToDto(updatedReportScore); - } +// @Transactional +// public ReportResponseDto updateReport(Long reportId, ReportRequestDto reportRequestDto) { +// Report existingReport = reportRepository.findById(reportId) +// .orElseThrow(() -> new IllegalArgumentException("Report not found with id: " + reportId)); +// existingReport.setCategoryName(reportRequestDto.getCategoryName()); +// Report updatedReport = reportRepository.save(existingReport); +// return convertToDto(updatedReport); +// } +// +// @Transactional +// public ReportResponseDto.ReportScoreResponseDto updateReportScore(Long reportScoreId, ReportRequestDto.ReportScoreRequestDto scoreRequestDto) { +// ReportScore existingReportScore = reportScoreRepository.findById(reportScoreId) +// .orElseThrow(() -> new IllegalArgumentException("ReportScore not found with id: " + reportScoreId)); +// existingReportScore.setSubject(scoreRequestDto.getSubject()); +// existingReportScore.setGrade(scoreRequestDto.getGrade()); +// existingReportScore.setAchievement(scoreRequestDto.getAchievement()); +// existingReportScore.setStudentNum(scoreRequestDto.getStudentNum()); +// existingReportScore.setStandardDeviation(scoreRequestDto.getStandardDeviation()); +// existingReportScore.setSubjectAverage(scoreRequestDto.getSubjectAverage()); +// existingReportScore.setScore(scoreRequestDto.getScore()); +// existingReportScore.setCredit(scoreRequestDto.getCredit()); +// Report parentReport = existingReportScore.getReport(); // ReportScore가 Report 참조를 가지고 있어야 함 +// if (parentReport != null) { +// parentReport.setCategoryGrade(calculateAverageFromList(parentReport.getScoreLists())); +// } +// ReportScore updatedReportScore = reportScoreRepository.save(existingReportScore); +// return convertToDto(updatedReportScore); +// } @Transactional - public void deleteReport(Long reportId) { - reportRepository.deleteById(reportId); + public void deleteReport(Long reportId, String userId) { + reportRepository.deleteByIdAndUser_Uid(reportId, userId); } private ReportResponseDto convertToDto(Report report) { diff --git a/src/main/java/hackerthon/likelion13th/canfly/login/controller/UserController.java b/src/main/java/hackerthon/likelion13th/canfly/login/controller/UserController.java index e9241a4..90cd2be 100644 --- a/src/main/java/hackerthon/likelion13th/canfly/login/controller/UserController.java +++ b/src/main/java/hackerthon/likelion13th/canfly/login/controller/UserController.java @@ -57,7 +57,7 @@ public ApiResponse deleteUser(Authentication auth) { return ApiResponse.onSuccess(SuccessCode.USER_DELETE_SUCCESS, 1); } - @Operation(summary = "토큰 사용 및 충전", description = "amount가 0이면 토큰 1개 사용, 0보다 크면 해당 양만큼 충전합니다.") + @Operation(summary = "토큰 사용 및 충전", description = "amount만큼 보유 토큰 수량에 더합니다. (음수 가능, 0 불가)") @PatchMapping("/token") public ApiResponse updateUserCoins( @AuthenticationPrincipal CustomUserDetails userDetails, // 또는 Authentication auth 객체 @@ -66,8 +66,6 @@ public ApiResponse updateUserCoins( String userPId = userDetails.getUsername(); User updatedUser = userService.processCoins(userPId, amount); CoinResponseDto responseDTO = CoinResponseDto.fromEntity(updatedUser); - - // 3. 최종적으로 변환된 DTO를 클라이언트에게 전달합니다. return ApiResponse.onSuccess(SuccessCode.TOKEN_PROCESS_SUCCESS, responseDTO); } diff --git a/src/main/java/hackerthon/likelion13th/canfly/login/service/UserService.java b/src/main/java/hackerthon/likelion13th/canfly/login/service/UserService.java index f5b6c05..0cc1475 100644 --- a/src/main/java/hackerthon/likelion13th/canfly/login/service/UserService.java +++ b/src/main/java/hackerthon/likelion13th/canfly/login/service/UserService.java @@ -147,23 +147,27 @@ public boolean needsProfile(String providerId) { @Transactional public boolean completeProfile(String providerId, ProfileRequestDto req) { User user = findUserByProviderId(providerId); + if (req.getSex() == null || req.getGradeNum() == null || req.getHighschool() == null || req.getAddress() == null) { + throw GeneralException.of(ErrorCode.INPUT_NOT_COMPLETED); + } + else { + user.setSex(req.getSex()); + user.setHighschool(req.getHighschool()); + user.setGradeNum(req.getGradeNum()); - user.setSex(req.getSex()); - user.setHighschool(req.getHighschool()); - user.setGradeNum(req.getGradeNum()); - - String zipcode = req.getZipcode(); - String address = req.getAddress(); - String detail = req.getAddressDetail(); + String zipcode = req.getZipcode(); + String address = req.getAddress(); + String detail = req.getAddressDetail(); - // 새로운 주소 설정 - Address newAddress = new Address(zipcode, address, detail); - user.updateAddress(newAddress); // User 엔티티에 주소 업데이트 - userRepository.save(user); + // 새로운 주소 설정 + Address newAddress = new Address(zipcode, address, detail); + user.updateAddress(newAddress); // User 엔티티에 주소 업데이트 + userRepository.save(user); - boolean stillNeeds = this.needsProfile(providerId); + boolean stillNeeds = this.needsProfile(providerId); - return !stillNeeds; + return !stillNeeds; + } } public String checkMemberByName(String username) {