Skip to content

Commit 82744d2

Browse files
authored
Merge pull request #10 from enjoy-hack/Daeun
Daeun
2 parents 19a3f53 + b1c0bf0 commit 82744d2

7 files changed

Lines changed: 226 additions & 1 deletion

File tree

src/main/java/com/example/enjoy/controller/HomeController.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@ public class HomeController {
1515
private final TrackService trackService;
1616

1717
@GetMapping("/home")
18+
public String showMyProgress(Model model) { // 1. Model 객체를 파라미터로 추가
19+
// TODO: 추후 Spring Security 등과 연동하여 실제 로그인한 사용자 ID를 가져와야 함
20+
String currentStudentId = "1"; // 2. 테스트용 임시 학생 ID 사용
21+
22+
// 3. 학생의 이수 현황을 계산하는 새로운 서비스 메서드 호출
23+
List<TrackProgressDto> progressData = trackService.calculateTrackProgress(currentStudentId);
24+
25+
// 4. 조회된 데이터를 "progressData"라는 이름으로 모델에 추가
26+
//model.addAttribute("progressData", progressData);
27+
28+
// 5. 데이터를 표시할 뷰(html)의 이름을 반환
29+
return "home";
1830
public List<TrackProgressDto> getProgress() {
1931
// 1. 반환 타입을 List<TrackProgressDto>로 변경
2032
String currentStudentId = "1";
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
package com.example.enjoy.controller;
22

3+
import org.springframework.web.bind.annotation.RestController;
4+
5+
@RestController
36
public class StudentDataController {
47
}
Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,77 @@
11
package com.example.enjoy.controller;
22

3+
import com.example.enjoy.dto.AddManualCourseRequest;
4+
import com.example.enjoy.dto.StudentCourseStatus;
5+
import com.example.enjoy.dto.loginDto.MemberCommand;
6+
import com.example.enjoy.dto.loginDto.MemberDto;
7+
import com.example.enjoy.entity.StudentCourse;
8+
import com.example.enjoy.entity.Track;
9+
import com.example.enjoy.service.loginService.SejongLoginService;
10+
import com.example.enjoy.service.userService.UserService;
11+
import io.swagger.v3.oas.annotations.Operation;
12+
import jakarta.validation.Valid;
13+
import okhttp3.OkHttpClient;
14+
import org.springframework.http.ResponseEntity;
15+
import org.springframework.web.bind.annotation.*;
16+
17+
import java.io.IOException;
18+
import java.util.List;
19+
import java.util.Map;
20+
21+
@RestController
22+
@RequestMapping("/api/student")
323
public class UserController {
4-
}
24+
25+
private final SejongLoginService sejongLoginService;
26+
private final UserService userService;
27+
28+
public UserController(SejongLoginService sejongLoginService, UserService userService) {
29+
this.sejongLoginService = sejongLoginService;
30+
this.userService = userService;
31+
}
32+
33+
@Operation(summary = "학생 정보 조회", description = "세종대학교 포털 인증을 통해 학생 정보를 조회합니다.")
34+
@GetMapping("/detail")
35+
public ResponseEntity<MemberDto> getStudentDetail(@RequestBody MemberCommand command) throws IOException {
36+
MemberDto memberInfo = sejongLoginService.getMemberAuthInfos(command);
37+
return ResponseEntity.ok(memberInfo);
38+
}
39+
40+
@Operation(summary = "수동 과목 등록", description = "학생이 직접 수강한 과목을 등록합니다.")
41+
@PostMapping("/courses")
42+
public ResponseEntity<Void> addManualCourse(@Valid @RequestBody AddManualCourseRequest request) {
43+
userService.addManualCourse(request);
44+
return ResponseEntity.ok().build();
45+
}
46+
47+
@Operation(summary = "수동 과목 삭제", description = "수동으로 등록한 과목을 삭제합니다.")
48+
@DeleteMapping("/courses")
49+
public ResponseEntity<Void> removeManualCourse(
50+
@RequestParam String studentId,
51+
@RequestParam String courseName) {
52+
userService.removeManualCourse(studentId, courseName);
53+
return ResponseEntity.ok().build();
54+
}
55+
56+
@Operation(summary = "완료 과목 조회", description = "학생이 수강 완료한 과목 목록을 조회합니다.")
57+
@GetMapping("/{studentId}/courses/completed")
58+
public ResponseEntity<List<StudentCourse>> getCompletedCourses(@PathVariable String studentId) {
59+
return ResponseEntity.ok(userService.getCompletedCourses(studentId));
60+
}
61+
62+
@Operation(summary = "트랙 진행률 조회", description = "학생의 각 트랙별 진행률을 조회합니다.")
63+
@GetMapping("/{studentId}/tracks/progress")
64+
public ResponseEntity<Map<Track, Double>> getTrackProgress(@PathVariable String studentId) {
65+
return ResponseEntity.ok(userService.getTrackProgress(studentId));
66+
}
67+
68+
@Operation(summary = "과목 상태 변경", description = "등록된 과목의 수강 상태를 변경합니다.")
69+
@PatchMapping("/courses/status")
70+
public ResponseEntity<Void> updateCourseStatus(
71+
@RequestParam String studentId,
72+
@RequestParam String courseName,
73+
@RequestParam StudentCourseStatus newStatus) {
74+
userService.updateCourseStatus(studentId, courseName, newStatus);
75+
return ResponseEntity.ok().build();
76+
}
77+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.example.enjoy.dto;
2+
3+
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.NotNull;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Builder;
7+
import lombok.Getter;
8+
import lombok.NoArgsConstructor;
9+
10+
11+
@Getter
12+
@Builder
13+
@NoArgsConstructor
14+
@AllArgsConstructor
15+
public class AddManualCourseRequest {
16+
17+
@NotBlank(message = "학번은 필수입니다.")
18+
private String studentId;
19+
20+
@NotBlank(message = "과목명은 필수입니다.")
21+
private String courseName;
22+
23+
@NotNull(message = "수강 상태는 필수입니다.")
24+
private StudentCourseStatus status;
25+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.example.enjoy.entity;
2+
3+
import jakarta.persistence.Entity;
4+
import jakarta.persistence.GeneratedValue;
5+
import jakarta.persistence.GenerationType;
6+
import jakarta.persistence.Id;
7+
8+
@Entity
9+
public class TrackCertification {
10+
@Id
11+
@GeneratedValue(strategy = GenerationType.IDENTITY)
12+
private Long id;
13+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
package com.example.enjoy.repository;
22

3+
import com.example.enjoy.dto.StudentCourseStatus;
34
import com.example.enjoy.entity.StudentCourse;
45
import org.springframework.data.jpa.repository.JpaRepository;
6+
import org.springframework.stereotype.Repository;
57
import org.springframework.transaction.annotation.Transactional;
68

79
import java.util.List;
10+
import java.util.Optional;
811

12+
@Repository
913
public interface StudentCourseRepository extends JpaRepository<StudentCourse, Long> {
1014

1115
List<StudentCourse> findByStudentId(String studentId);
1216

17+
boolean existsByStudentIdAndCourseName(String studentId, String courseName);
18+
19+
Optional<StudentCourse> findByStudentIdAndCourseNameAndManualIsTrue(String studentId, String courseName);
20+
21+
List<StudentCourse> findAllByStudentIdAndStatus(String studentId, StudentCourseStatus status);
22+
23+
Optional<StudentCourse> findByStudentIdAndCourseName(String studentId, String courseName);
1324

1425
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.example.enjoy.service.userService;
2+
3+
import com.amazonaws.services.cloudformation.model.AlreadyExistsException;
4+
import com.example.enjoy.dto.AddManualCourseRequest;
5+
import com.example.enjoy.dto.StudentCourseStatus;
6+
import com.example.enjoy.entity.StudentCourse;
7+
import com.example.enjoy.entity.Track;
8+
import com.example.enjoy.entity.TrackCourse;
9+
import com.example.enjoy.repository.StudentCourseRepository;
10+
import com.example.enjoy.repository.TrackCourseRepository;
11+
import com.example.enjoy.repository.TrackRepository;
12+
import lombok.RequiredArgsConstructor;
13+
import org.springframework.stereotype.Service;
14+
import org.springframework.transaction.annotation.Transactional;
15+
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.stream.Collectors;
19+
20+
@Service
21+
@RequiredArgsConstructor
22+
@Transactional(readOnly = true)
23+
public class UserService {
24+
25+
private final StudentCourseRepository studentCourseRepository;
26+
private final TrackRepository trackRepository;
27+
private final TrackCourseRepository trackCourseRepository;
28+
29+
@Transactional
30+
public void addManualCourse(AddManualCourseRequest request) { //수동으로 과목 등록
31+
if (studentCourseRepository.existsByStudentIdAndCourseName(
32+
request.getStudentId(),
33+
request.getCourseName())) {
34+
throw new AlreadyExistsException("이미 등록된 과목입니다.");
35+
}
36+
37+
StudentCourse sc = StudentCourse.builder() //수강 여부 설정 가능
38+
.studentId(request.getStudentId())
39+
.courseName(request.getCourseName())
40+
.status(request.getStatus())
41+
.manual(true)
42+
.build();
43+
studentCourseRepository.save(sc);
44+
}
45+
46+
47+
@Transactional
48+
public void removeManualCourse(String studentId, String courseName) { //수동 등록 과목 삭제
49+
StudentCourse course = studentCourseRepository.findByStudentIdAndCourseNameAndManualIsTrue(studentId, courseName)
50+
.orElseThrow(() -> new IllegalArgumentException("수동 등록된 과목을 찾을 수 없습니다."));
51+
studentCourseRepository.delete(course);
52+
}
53+
54+
public List<StudentCourse> getCompletedCourses(String studentId) { //수강 완료 과목 조회
55+
return studentCourseRepository.findAllByStudentIdAndStatus(studentId, StudentCourseStatus.COMPLETED);
56+
}
57+
58+
public Map<Track, Double> getTrackProgress(String studentId) { //트랙별 진행률 조회
59+
List<Track> allTracks = trackRepository.findAll();
60+
List<StudentCourse> completedCourses = getCompletedCourses(studentId);
61+
62+
return allTracks.stream().collect(Collectors.toMap(
63+
track -> track,
64+
track -> calculateTrackProgress(track, completedCourses)
65+
));
66+
}
67+
68+
private double calculateTrackProgress(Track track, List<StudentCourse> completedCourses) {
69+
List<TrackCourse> trackCourses = trackCourseRepository.findAllByTrack(track);
70+
if (trackCourses.isEmpty()) return 0.0;
71+
72+
long completedCount = trackCourses.stream()
73+
.filter(trackCourse -> completedCourses.stream()
74+
.anyMatch(completed -> completed.getCourseName().equals(trackCourse.getCourseName())))
75+
.count();
76+
77+
return (double) completedCount / trackCourses.size() * 100;
78+
}
79+
80+
@Transactional
81+
public void updateCourseStatus(String studentId, String courseName, StudentCourseStatus newStatus) {
82+
StudentCourse course = studentCourseRepository
83+
.findByStudentIdAndCourseName(studentId, courseName)
84+
.orElseThrow(() -> new IllegalArgumentException("등록된 과목을 찾을 수 없습니다."));
85+
86+
course.updateStatus(newStatus);
87+
}
88+
}

0 commit comments

Comments
 (0)