Skip to content

Commit cfa98bb

Browse files
authored
Merge pull request #43 from gotothesky2/refactor/univmajorbookmark
Refactor/univmajorbookmark
2 parents 9d49382 + 18b62cd commit cfa98bb

File tree

13 files changed

+356
-7
lines changed

13 files changed

+356
-7
lines changed

src/main/java/hackerthon/likelion13th/canfly/domain/field/FieldBookmark.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import org.hibernate.annotations.OnDeleteAction;
99

1010
@Entity
11-
@Table(name = "fieldBookmark")
11+
@Table(name = "field_bookmark")
1212
@Getter
1313
@Setter
1414
@NoArgsConstructor

src/main/java/hackerthon/likelion13th/canfly/domain/major/MajorBookmark.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package hackerthon.likelion13th.canfly.domain.major;
22

33
import hackerthon.likelion13th.canfly.domain.entity.BaseEntity;
4-
import hackerthon.likelion13th.canfly.domain.field.Field;
4+
import hackerthon.likelion13th.canfly.domain.university.University;
55
import hackerthon.likelion13th.canfly.domain.user.User;
66
import jakarta.persistence.*;
77
import lombok.*;
88
import org.hibernate.annotations.OnDelete;
99
import org.hibernate.annotations.OnDeleteAction;
1010

1111
@Entity
12-
@Table(name = "majorBookmark")
12+
@Table(name = "major_bookmark")
1313
@Getter
1414
@Setter
1515
@NoArgsConstructor
@@ -30,4 +30,9 @@ public class MajorBookmark extends BaseEntity {
3030
@JoinColumn(name = "uid", nullable = false)
3131
@OnDelete(action = OnDeleteAction.CASCADE)
3232
private User user;
33+
34+
@ManyToOne(fetch = FetchType.LAZY, optional = true)
35+
@JoinColumn(name = "univ_id", nullable = true)
36+
@OnDelete(action = OnDeleteAction.CASCADE)
37+
private University university;
3338
}

src/main/java/hackerthon/likelion13th/canfly/global/api/ErrorCode.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ public enum ErrorCode implements BaseCode { // 실패
2323
TOKEN_NO_AUTH(HttpStatus.FORBIDDEN, "JWT_4033", "권한 정보가 없는 token입니다."),
2424
TOKEN_EXPIRED(HttpStatus.UNAUTHORIZED, "JWT_4011", "token 유효기간이 만료되었습니다."),
2525

26+
// FIELD
27+
FIELD_NOT_FOUND(HttpStatus.NOT_FOUND, "FIELD_4041", "일치하는 FIELD가 없습니다."),
28+
29+
// Major
30+
MAJOR_NOT_FOUND(HttpStatus.NOT_FOUND, "MAJOR_4041", "일치하는 MAJOR가 없습니다."),
31+
32+
// University
33+
UNIVERSITY_NOT_FOUND(HttpStatus.NOT_FOUND, "UNIVERSITY_4041", "일치하는 UNIVERSITY가 없습니다."),
34+
2635
// Mock
2736
MOCK_NOT_FOUND(HttpStatus.NOT_FOUND, "MOCK_4041", "찾으려는 모의고사가 존재하지 않습니다.");
2837

src/main/java/hackerthon/likelion13th/canfly/global/api/SuccessCode.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ public enum SuccessCode implements BaseCode { // 성공
3737

3838
// 형이 추가한 코드
3939
MAJORSYNC_BULK_SUCCESS(HttpStatus.OK, "Sync_2012", "DB 동기화가 완료되었습니다."),
40+
FIELD_LIKE_SUCCESS(HttpStatus.OK, "FIELD_MARK_2001", "계열 북마크 성공"),
41+
MAJOR_LIKE_SUCCESS(HttpStatus.OK, "MAJOR_MARK_2001", "전공 북마크 성공"),
42+
MAJOR_UNIV_LIKE_SUCCESS(HttpStatus.OK, "MAJOR_UNIV_MARK_2001", "전공+대학 북마크 성공"),
43+
FIELD_LIKED_LIST_VIEW_SUCCESS(HttpStatus.OK, "FIELD_2006", "로그인 사용자가 북마크한 모든 계열명을 반환합니다."),
44+
FIELD_LIST_VIEW_SUCCESS(HttpStatus.OK, "FIELD_2007", "계열 전체 조회 완료."),
4045

4146
// 내가 추가한 코드
4247
TOKEN_PROCESS_SUCCESS(HttpStatus.OK, "TOKEN_2001", "코인(토큰) 사용이 완료되었습니다.");
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,59 @@
11
package hackerthon.likelion13th.canfly.search.controller;
22

3+
import hackerthon.likelion13th.canfly.domain.user.User;
4+
import hackerthon.likelion13th.canfly.global.api.ApiResponse;
5+
import hackerthon.likelion13th.canfly.global.api.SuccessCode;
6+
import hackerthon.likelion13th.canfly.login.auth.mapper.CustomUserDetails;
7+
import hackerthon.likelion13th.canfly.login.service.UserService;
8+
import hackerthon.likelion13th.canfly.search.dto.FieldDto;
9+
import hackerthon.likelion13th.canfly.search.repository.FieldBookmarkRepository;
10+
import hackerthon.likelion13th.canfly.search.service.FieldService;
11+
import io.swagger.v3.oas.annotations.Operation;
12+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
13+
import io.swagger.v3.oas.annotations.tags.Tag;
14+
import lombok.RequiredArgsConstructor;
15+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
16+
import org.springframework.web.bind.annotation.GetMapping;
17+
import org.springframework.web.bind.annotation.RequestMapping;
18+
import org.springframework.web.bind.annotation.RestController;
19+
20+
import java.util.List;
21+
22+
@Tag(name = "계열 조회", description = "계열 관련 API")
23+
@RestController
24+
@RequestMapping("/field")
25+
@RequiredArgsConstructor
326
public class FieldController {
27+
private final UserService userService;
28+
private final FieldService fieldService;
29+
private final FieldBookmarkRepository fieldBookmarkRepository;
30+
31+
@Operation(summary = "내가 좋아요한 계열 전체", description = "로그인 사용자가 북마크한 모든 계열을 반환합니다.")
32+
@ApiResponses({
33+
@io.swagger.v3.oas.annotations.responses.
34+
ApiResponse(responseCode = "FIELD_2006", description = "내 북마크 계열 전체 조회 완료")
35+
})
36+
@GetMapping("/like")
37+
public ApiResponse<List<FieldDto>> getMyLikedFields(
38+
@AuthenticationPrincipal CustomUserDetails customUserDetails
39+
) {
40+
User user = userService.findUserByProviderId(customUserDetails.getUsername());
41+
List<FieldDto> fields = fieldService.getAllLikedFields(user);
42+
43+
return ApiResponse.onSuccess(SuccessCode.FIELD_LIKED_LIST_VIEW_SUCCESS, fields);
44+
}
45+
46+
@Operation(summary = "계열 전체", description = "모든 계열을 반환합니다.")
47+
@ApiResponses({
48+
@io.swagger.v3.oas.annotations.responses.
49+
ApiResponse(responseCode = "FIELD_2007", description = "계열 전체 조회 완료")
50+
})
51+
@GetMapping("/all")
52+
public ApiResponse<List<FieldDto>> getFields(
53+
@AuthenticationPrincipal CustomUserDetails customUserDetails
54+
) {
55+
List<FieldDto> fields = fieldService.getAllFields();
56+
57+
return ApiResponse.onSuccess(SuccessCode.FIELD_LIST_VIEW_SUCCESS, fields);
58+
}
459
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package hackerthon.likelion13th.canfly.search.controller;
2+
3+
import hackerthon.likelion13th.canfly.domain.user.User;
4+
import hackerthon.likelion13th.canfly.global.api.ApiResponse;
5+
import hackerthon.likelion13th.canfly.global.api.SuccessCode;
6+
import hackerthon.likelion13th.canfly.login.auth.mapper.CustomUserDetails;
7+
import hackerthon.likelion13th.canfly.login.service.UserService;
8+
import hackerthon.likelion13th.canfly.search.service.FieldService;
9+
import io.swagger.v3.oas.annotations.Operation;
10+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
11+
import io.swagger.v3.oas.annotations.tags.Tag;
12+
import lombok.RequiredArgsConstructor;
13+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
14+
import org.springframework.web.bind.annotation.PathVariable;
15+
import org.springframework.web.bind.annotation.PostMapping;
16+
import org.springframework.web.bind.annotation.RequestMapping;
17+
import org.springframework.web.bind.annotation.RestController;
18+
19+
@Tag(name = "계열 북마크", description = "계열 북마크 컨트롤러입니다")
20+
@RestController
21+
@RequestMapping("/field/{fieldId}/like")
22+
@RequiredArgsConstructor
23+
public class FieldMarkController {
24+
private final UserService userService;
25+
private final FieldService fieldService;
26+
27+
@Operation(summary = "계열 북마크", description = "계열에 북마크를 추가하거나 취소하는 api.")
28+
@ApiResponses(value = {
29+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "FIELD_MARK_2001", description = "계열 북마크 성공")
30+
})
31+
@PostMapping("/toggle")
32+
public ApiResponse<Boolean> toggleLike(
33+
@PathVariable(name = "fieldId") Long fieldId,
34+
@AuthenticationPrincipal CustomUserDetails customUserDetails
35+
) {
36+
User user = userService.findUserByProviderId(customUserDetails.getUsername());
37+
fieldService.toggleFieldLike(fieldId, user);
38+
39+
return ApiResponse.onSuccess(SuccessCode.FIELD_LIKE_SUCCESS, true);
40+
}
41+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package hackerthon.likelion13th.canfly.search.controller;
2+
3+
import hackerthon.likelion13th.canfly.domain.user.User;
4+
import hackerthon.likelion13th.canfly.global.api.ApiResponse;
5+
import hackerthon.likelion13th.canfly.global.api.SuccessCode;
6+
import hackerthon.likelion13th.canfly.login.auth.mapper.CustomUserDetails;
7+
import hackerthon.likelion13th.canfly.login.service.UserService;
8+
import hackerthon.likelion13th.canfly.search.service.MajorService;
9+
import io.swagger.v3.oas.annotations.Operation;
10+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
11+
import io.swagger.v3.oas.annotations.tags.Tag;
12+
import lombok.RequiredArgsConstructor;
13+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
14+
import org.springframework.web.bind.annotation.PathVariable;
15+
import org.springframework.web.bind.annotation.PostMapping;
16+
import org.springframework.web.bind.annotation.RequestMapping;
17+
import org.springframework.web.bind.annotation.RestController;
18+
19+
@Tag(name = "전공 및 전공-대학 북마크", description = "전공 북마크 컨트롤러입니다")
20+
@RestController
21+
@RequestMapping("/major/{majorId}/like")
22+
@RequiredArgsConstructor
23+
public class MajorMarkController {
24+
private final UserService userService;
25+
private final MajorService majorService;
26+
27+
@Operation(summary = "전공 북마크", description = "전공에 북마크를 추가하거나 취소하는 api.")
28+
@ApiResponses(value = {
29+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "MAJOR_MARK_2001", description = "계열 북마크 성공")
30+
})
31+
@PostMapping("/toggle")
32+
public ApiResponse<Boolean> toggleLike(
33+
@PathVariable(name = "majorId") Long majorId,
34+
@AuthenticationPrincipal CustomUserDetails customUserDetails
35+
) {
36+
User user = userService.findUserByProviderId(customUserDetails.getUsername());
37+
majorService.toggleMajorLike(majorId, user);
38+
39+
return ApiResponse.onSuccess(SuccessCode.MAJOR_LIKE_SUCCESS, true);
40+
}
41+
42+
@Operation(summary = "전공+대학 북마크 토글", description = "전공/대학 조합 북마크를 토글합니다.")
43+
@PostMapping("/univ/{univId}/toggle")
44+
public ApiResponse<Boolean> toggleLikeWithUniv(
45+
@PathVariable Long majorId,
46+
@PathVariable Long univId,
47+
@AuthenticationPrincipal CustomUserDetails customUserDetails
48+
) {
49+
User user = userService.findUserByProviderId(customUserDetails.getUsername());
50+
majorService.toggleMajorUnivLike(majorId, univId, user);
51+
return ApiResponse.onSuccess(SuccessCode.MAJOR_UNIV_LIKE_SUCCESS, true);
52+
}
53+
}
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
11
package hackerthon.likelion13th.canfly.search.dto;
22

3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
8+
@Data
9+
@NoArgsConstructor
10+
@AllArgsConstructor
11+
@Builder
312
public class FieldDto {
4-
}
13+
private Long id; // field_id
14+
private String name; // field_name
15+
}
Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,32 @@
11
package hackerthon.likelion13th.canfly.search.repository;
22

3-
public interface FieldBookmarkRepository {
3+
import hackerthon.likelion13th.canfly.domain.field.Field;
4+
import hackerthon.likelion13th.canfly.domain.field.FieldBookmark;
5+
import hackerthon.likelion13th.canfly.domain.user.User;
6+
import io.lettuce.core.dynamic.annotation.Param;
7+
import org.springframework.data.jpa.repository.JpaRepository;
8+
import org.springframework.data.jpa.repository.Modifying;
9+
import org.springframework.data.jpa.repository.Query;
10+
11+
import java.util.List;
12+
13+
public interface FieldBookmarkRepository extends JpaRepository<FieldBookmark, Long> {
14+
15+
boolean existsByUserAndField(User user, Field field);
16+
17+
void deleteByUserAndField(User user, Field field);
18+
19+
@Modifying
20+
@Query(value = "INSERT INTO field_bookmark (uid, f_id) VALUES (:userId, :fieldId) " +
21+
"ON DUPLICATE KEY UPDATE fb_id = LAST_INSERT_ID(fb_id)", nativeQuery = true)
22+
void insertOrUpdateFieldMark(@Param("userId") String userId, @Param("fieldId") Long fieldId);
23+
24+
@Query(value = """
25+
SELECT f.f_id AS id, f.f_name AS name
26+
FROM field_bookmark fb
27+
JOIN field f ON fb.f_id = f.f_id
28+
WHERE fb.uid = :userId
29+
ORDER BY fb.created_at DESC, fb.fb_id DESC
30+
""", nativeQuery = true)
31+
List<Object[]> findAllLikedFields(@Param("userId") String userId);
432
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
package hackerthon.likelion13th.canfly.search.repository;
22

3-
public interface FieldRepository {
3+
import hackerthon.likelion13th.canfly.domain.field.Field;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
public interface FieldRepository extends JpaRepository<Field, Long> {
47
}

0 commit comments

Comments
 (0)