From 180dc7c30f6a2c0be7538da83f69d310ee8fa2be Mon Sep 17 00:00:00 2001 From: DaeunSon <130820902+DaeunSon@users.noreply.github.com> Date: Thu, 26 Jun 2025 02:46:49 +0900 Subject: [PATCH] =?UTF-8?q?Feat=20:=20=EA=B4=80=EC=8B=AC=20=ED=8A=B8?= =?UTF-8?q?=EB=9E=99=20=EC=B6=94=EA=B0=80=20=EC=A1=B0=ED=9A=8C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enjoy/controller/UserTrackController.java | 59 ++++++++++++++++ .../com/example/enjoy/dto/TrackDetailDto.java | 8 +++ .../example/enjoy/dto/UserTrackResponse.java | 22 ++++++ .../java/com/example/enjoy/entity/Track.java | 10 +++ .../com/example/enjoy/entity/UserTrack.java | 28 ++++++++ .../com/example/enjoy/entity/user/User.java | 7 ++ .../enjoy/repository/TrackRepository.java | 2 + .../enjoy/repository/UserTrackRepository.java | 18 +++++ .../enjoy/service/UserTrackService.java | 68 +++++++++++++++++++ .../loginService/SejongLoginService.java | 11 --- 10 files changed, 222 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/example/enjoy/controller/UserTrackController.java create mode 100644 src/main/java/com/example/enjoy/dto/UserTrackResponse.java create mode 100644 src/main/java/com/example/enjoy/entity/UserTrack.java create mode 100644 src/main/java/com/example/enjoy/repository/UserTrackRepository.java create mode 100644 src/main/java/com/example/enjoy/service/UserTrackService.java diff --git a/src/main/java/com/example/enjoy/controller/UserTrackController.java b/src/main/java/com/example/enjoy/controller/UserTrackController.java new file mode 100644 index 0000000..86309c9 --- /dev/null +++ b/src/main/java/com/example/enjoy/controller/UserTrackController.java @@ -0,0 +1,59 @@ +package com.example.enjoy.controller; + +import com.example.enjoy.dto.TrackDetailDto; +import com.example.enjoy.dto.UserTrackResponse; +import com.example.enjoy.entity.Track; +import com.example.enjoy.entity.UserTrack; +import com.example.enjoy.entity.user.User; +import com.example.enjoy.service.UserTrackService; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/user-track") +public class UserTrackController { + private final UserTrackService userTrackService; + + public UserTrackController(UserTrackService userTrackService) { + this.userTrackService = userTrackService; + } + + @Operation(summary = "사용자 관심 트랙 추가", description = "사용자가 관심 트랙을 추가합니다.") + @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity addUserTrack( + @RequestParam String studentId, + @RequestParam String trackName) { + UserTrack savedUserTrack = userTrackService.addUserTrack(studentId, trackName); + UserTrackResponse response = UserTrackResponse.from(savedUserTrack); + return ResponseEntity.ok(response); + } + + @Operation(summary = "사용자 관심 트랙 조회", description = "사용자가 추가한 관심 트랙 목록을 조회합니다.") + @GetMapping("/{studentId}") + public ResponseEntity> getUserTracks( + @PathVariable String studentId) { + List tracks = userTrackService.getUserTracks(studentId); + if (tracks.isEmpty()) { + return ResponseEntity.noContent().build(); + } + else{ + List trackDetails = tracks.stream() + .map(track -> new TrackDetailDto().from(track)) + .toList(); + return ResponseEntity.ok(trackDetails); + } + } + + @Operation(summary = "사용자 관심 트랙 삭제", description = "사용자가 추가한 관심 트랙을 삭제합니다.") + @DeleteMapping + public ResponseEntity removeUserTrack( + @RequestParam String studentId, + @RequestParam String trackName) { + userTrackService.removeUserTrack(studentId, trackName); + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/example/enjoy/dto/TrackDetailDto.java b/src/main/java/com/example/enjoy/dto/TrackDetailDto.java index f69fee5..84a465f 100644 --- a/src/main/java/com/example/enjoy/dto/TrackDetailDto.java +++ b/src/main/java/com/example/enjoy/dto/TrackDetailDto.java @@ -1,5 +1,6 @@ package com.example.enjoy.dto; +import com.example.enjoy.entity.Track; import lombok.Data; import lombok.Getter; import lombok.Setter; @@ -16,4 +17,11 @@ public class TrackDetailDto { private String department; private String description; // 트랙에 대한 설명 추가 private List courses; // 트랙에 포함된 과목 목록 + + public TrackDetailDto from (Track track) { + this.trackId = track.getId(); + this.trackName = track.getName(); + this.department = track.getDepartment(); + return this; + } } diff --git a/src/main/java/com/example/enjoy/dto/UserTrackResponse.java b/src/main/java/com/example/enjoy/dto/UserTrackResponse.java new file mode 100644 index 0000000..e80ef37 --- /dev/null +++ b/src/main/java/com/example/enjoy/dto/UserTrackResponse.java @@ -0,0 +1,22 @@ +package com.example.enjoy.dto; + +import com.example.enjoy.entity.FavoriteCourse; +import com.example.enjoy.entity.UserTrack; +import lombok.*; + +import java.time.LocalDateTime; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UserTrackResponse { + private String studentId; + private String trackName; + + public static UserTrackResponse from(UserTrack userTrack) { + return new UserTrackResponse( + userTrack.getUser().getStudentId(), + userTrack.getTrack().getName() + ); + } +} diff --git a/src/main/java/com/example/enjoy/entity/Track.java b/src/main/java/com/example/enjoy/entity/Track.java index ca64b5a..7c5156a 100644 --- a/src/main/java/com/example/enjoy/entity/Track.java +++ b/src/main/java/com/example/enjoy/entity/Track.java @@ -18,6 +18,16 @@ public class Track { @OneToMany(mappedBy = "track", cascade = CascadeType.ALL) private List courses = new ArrayList<>(); + + @OneToMany(mappedBy = "track", cascade = CascadeType.ALL) + private List userTracks = new ArrayList<>(); + + public void addUserTrack(UserTrack userTrack) { + userTracks.add(userTrack); + userTrack.setTrack(this); + } + + // public void addCourse(TrackCourse course) { // courses.add(course); // course.setTrack(this); diff --git a/src/main/java/com/example/enjoy/entity/UserTrack.java b/src/main/java/com/example/enjoy/entity/UserTrack.java new file mode 100644 index 0000000..0f27e6c --- /dev/null +++ b/src/main/java/com/example/enjoy/entity/UserTrack.java @@ -0,0 +1,28 @@ +package com.example.enjoy.entity; + +import com.example.enjoy.entity.user.User; +import com.example.enjoy.util.BaseEntity; +import jakarta.persistence.*; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Entity +@Getter +@Setter +public class UserTrack extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "track_id") + private Track track; + +} diff --git a/src/main/java/com/example/enjoy/entity/user/User.java b/src/main/java/com/example/enjoy/entity/user/User.java index 9a8c8d4..32a73ed 100644 --- a/src/main/java/com/example/enjoy/entity/user/User.java +++ b/src/main/java/com/example/enjoy/entity/user/User.java @@ -2,9 +2,13 @@ import com.example.enjoy.entity.BaseTimeEntity; +import com.example.enjoy.entity.UserTrack; import jakarta.persistence.*; import lombok.*; +import java.util.ArrayList; +import java.util.List; + @Builder @Entity @Getter @@ -31,6 +35,9 @@ public class User extends BaseTimeEntity { @Column(nullable = false) private String completedSemester; + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) + private List userTracks = new ArrayList<>(); + public void updateUserInfo(String studentId, String username, String major, String grade, String completedSemester) { this.studentId = studentId; this.username = username; diff --git a/src/main/java/com/example/enjoy/repository/TrackRepository.java b/src/main/java/com/example/enjoy/repository/TrackRepository.java index c35d37c..6cfb305 100644 --- a/src/main/java/com/example/enjoy/repository/TrackRepository.java +++ b/src/main/java/com/example/enjoy/repository/TrackRepository.java @@ -20,4 +20,6 @@ public interface TrackRepository extends JpaRepository { */ @Query("SELECT t FROM Track t JOIN FETCH t.courses WHERE t.id = :trackId") Optional findByIdWithCourses(@Param("trackId") Long trackId); + + Optional findByName(String name); } \ No newline at end of file diff --git a/src/main/java/com/example/enjoy/repository/UserTrackRepository.java b/src/main/java/com/example/enjoy/repository/UserTrackRepository.java new file mode 100644 index 0000000..4de97a4 --- /dev/null +++ b/src/main/java/com/example/enjoy/repository/UserTrackRepository.java @@ -0,0 +1,18 @@ +package com.example.enjoy.repository; + +import com.example.enjoy.entity.Track; +import com.example.enjoy.entity.UserTrack; +import com.example.enjoy.entity.user.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface UserTrackRepository extends JpaRepository { + + List findAllByUser(User user); + + Optional findByUserAndTrack(User user, Track track); +} diff --git a/src/main/java/com/example/enjoy/service/UserTrackService.java b/src/main/java/com/example/enjoy/service/UserTrackService.java new file mode 100644 index 0000000..e3e380d --- /dev/null +++ b/src/main/java/com/example/enjoy/service/UserTrackService.java @@ -0,0 +1,68 @@ +package com.example.enjoy.service; + +import com.example.enjoy.entity.Track; +import com.example.enjoy.entity.UserTrack; +import com.example.enjoy.entity.user.User; +import com.example.enjoy.repository.TrackRepository; +import com.example.enjoy.repository.UserRepository; +import com.example.enjoy.repository.UserTrackRepository; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class UserTrackService { + + private final TrackRepository trackRepository; + private final UserRepository userRepository; + private final UserTrackRepository userTrackRepository; + + public UserTrackService(TrackRepository trackRepository, UserRepository userRepository, UserTrackRepository userTrackRepository) { + this.trackRepository = trackRepository; + this.userRepository = userRepository; + this.userTrackRepository = userTrackRepository; + } + + public UserTrack addUserTrack(String studentId, String trackName) { + User user = userRepository.findByStudentId(studentId) + .orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다.")); + + Track track = trackRepository.findByName(trackName) + .orElseThrow(() -> new RuntimeException("트랙을 찾을 수 없습니다.")); + + UserTrack userTrack = new UserTrack(); + userTrack.setUser(user); + userTrack.setTrack(track); + + userTrackRepository.save(userTrack); + return userTrack; + } + + public List getUserTracks(String studentId) { + User user = userRepository.findByStudentId(studentId) + .orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다.")); + + return userTrackRepository.findAllByUser(user) + .stream() + .map(UserTrack::getTrack) + .collect(Collectors.toList()); + } + + // 관심 트랙 삭제 + public void removeUserTrack(String studentId, String trackName) { + User user = userRepository.findByStudentId(studentId) + .orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다.")); + + Track track = trackRepository.findByName(trackName) + .orElseThrow(() -> new RuntimeException("트랙을 찾을 수 없습니다.")); + + UserTrack userTrack = userTrackRepository.findByUserAndTrack(user, track) + .orElseThrow(() -> new RuntimeException("사용자 트랙을 찾을 수 없습니다.")); + + userTrackRepository.delete(userTrack); + } + + +} diff --git a/src/main/java/com/example/enjoy/service/loginService/SejongLoginService.java b/src/main/java/com/example/enjoy/service/loginService/SejongLoginService.java index 746e882..eebf95f 100644 --- a/src/main/java/com/example/enjoy/service/loginService/SejongLoginService.java +++ b/src/main/java/com/example/enjoy/service/loginService/SejongLoginService.java @@ -11,19 +11,8 @@ import com.example.enjoy.repository.UserRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import okhttp3.*; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; import org.springframework.stereotype.Service; -import okhttp3.JavaNetCookieJar; -import javax.net.ssl.*; import java.io.IOException; -import java.net.CookieManager; -import java.net.CookiePolicy; -import java.net.SocketTimeoutException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; @Slf4j @Service