Skip to content

Commit 973377c

Browse files
authored
Merge pull request #46 from Hsu-Connect/feat/#45
[#45] Feat: 마이페이지 화면 상단 사용자요약카드 조회 API 구현
2 parents 7a744c5 + c749601 commit 973377c

8 files changed

Lines changed: 151 additions & 0 deletions

File tree

src/main/java/hansung/hansung_connect/config/SecurityConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
4444
// 개발 중 테스트할 API 임시 허용
4545
.requestMatchers("/users/me/careers/**").permitAll()
4646
.requestMatchers("/links/**").permitAll()
47+
.requestMatchers("/users/**").permitAll()
4748
// 그 외는 인증 필요
4849
.anyRequest().authenticated()
4950
)

src/main/java/hansung/hansung_connect/domain/career/repository/CareerRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
import org.springframework.data.jpa.repository.JpaRepository;
55

66
public interface CareerRepository extends JpaRepository<Career, Long> {
7+
boolean existsByUser_IdAndIsEmployedTrue(Long userId);
78
}
89

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package hansung.hansung_connect.domain.user.controller;
2+
3+
import hansung.hansung_connect.common.response.ApiResponse;
4+
import hansung.hansung_connect.domain.user.dto.UserResponseDTO;
5+
import hansung.hansung_connect.domain.user.dto.UserResponseDTO.SummaryCardResponse;
6+
import hansung.hansung_connect.domain.user.service.UserQueryService;
7+
import io.swagger.v3.oas.annotations.Operation;
8+
import io.swagger.v3.oas.annotations.tags.Tag;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.http.ResponseEntity;
11+
import org.springframework.web.bind.annotation.GetMapping;
12+
import org.springframework.web.bind.annotation.RequestMapping;
13+
import org.springframework.web.bind.annotation.RestController;
14+
15+
@Tag(name = "User", description = "유저/프로필 조회 API")
16+
@RestController
17+
@RequestMapping("/users")
18+
@RequiredArgsConstructor
19+
public class UserController {
20+
21+
private final UserQueryService userQueryService;
22+
23+
@Operation(
24+
summary = "마이페이지 상단 사용자요약카드",
25+
description = """
26+
마이페이지 상단 카드에 필요한 최소 사용자 정보를 반환합니다.
27+
<br><br>
28+
필드 정보
29+
- studentNumberPrefix: 학번 앞 두 자리 (예: "21")
30+
- major: 전공
31+
- jobSeeking: 구직 여부 (구직중/구직중아님)
32+
- academicStatus: 학교관련 상태
33+
- (ENROLLED:재학중/GRADUATED:졸업/EXPECTED_GRADUATION:졸업예정/COMPLETED:수료/LEAVE_OF_ABSENCE:휴학)
34+
- employed: 현재 재직상태 (재직중/재직중아님)
35+
"""
36+
)
37+
@GetMapping("/summary")
38+
public ResponseEntity<ApiResponse<SummaryCardResponse>> getMySummaryCard() {
39+
// TODO: 실제 배포 시 SecurityContext에서 userId 추출
40+
Long currentUserId = 1L;
41+
42+
UserResponseDTO.SummaryCardResponse result =
43+
userQueryService.getMySummaryCard(currentUserId);
44+
45+
return ResponseEntity.ok(ApiResponse.onSuccess(result));
46+
}
47+
}
48+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package hansung.hansung_connect.domain.user.converter;
2+
3+
import hansung.hansung_connect.domain.user.dto.UserResponseDTO;
4+
import hansung.hansung_connect.domain.user.entity.User;
5+
import org.springframework.stereotype.Component;
6+
7+
@Component
8+
public class UserConverter {
9+
public UserResponseDTO.SummaryCardResponse toSummaryCardResponse(User user, boolean employed) {
10+
return UserResponseDTO.SummaryCardResponse.builder()
11+
.userId(user.getId())
12+
.name(user.getName())
13+
.studentNumberPrefix(extractStudentNumberPrefix(user.getStudentNumber()))
14+
.major(user.getMajor())
15+
.jobSeeking(user.isJobSeeking())
16+
.academicStatus(user.getAcademicStatus())
17+
.employed(employed)
18+
.build();
19+
}
20+
21+
// 학번 앞 두 자리만 반환
22+
private String extractStudentNumberPrefix(String studentNumber) {
23+
if (studentNumber == null) {
24+
return "";
25+
}
26+
String trimmed = studentNumber.trim();
27+
if (trimmed.length() < 2) {
28+
return "";
29+
}
30+
return trimmed.substring(0, 2);
31+
}
32+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package hansung.hansung_connect.domain.user.dto;
2+
3+
public class UserRequestDTO {
4+
5+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package hansung.hansung_connect.domain.user.dto;
2+
3+
import hansung.hansung_connect.domain.user.entity.enums.AcademicStatus;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
9+
public class UserResponseDTO {
10+
@Getter
11+
@NoArgsConstructor
12+
@AllArgsConstructor
13+
@Builder
14+
public static class SummaryCardResponse {
15+
private Long userId; // 사용자 PK
16+
private String name; // 이름
17+
private String studentNumberPrefix; // 학번 앞 두 자리 (예: "21")
18+
private String major; // 전공
19+
private boolean jobSeeking; // 구직 여부
20+
private AcademicStatus academicStatus; // 재학/졸업 등 상태
21+
private boolean employed; // 재직 중 여부 (Career.isEmployed 존재 여부)
22+
}
23+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package hansung.hansung_connect.domain.user.service;
2+
3+
import hansung.hansung_connect.domain.user.dto.UserResponseDTO;
4+
5+
public interface UserQueryService {
6+
UserResponseDTO.SummaryCardResponse getMySummaryCard(Long currentUserId);
7+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package hansung.hansung_connect.domain.user.service;
2+
3+
import hansung.hansung_connect.common.exception.GeneralException;
4+
import hansung.hansung_connect.common.exception.code.status.ErrorStatus;
5+
import hansung.hansung_connect.domain.career.repository.CareerRepository;
6+
import hansung.hansung_connect.domain.user.converter.UserConverter;
7+
import hansung.hansung_connect.domain.user.dto.UserResponseDTO;
8+
import hansung.hansung_connect.domain.user.entity.User;
9+
import hansung.hansung_connect.domain.user.repository.UserRepository;
10+
import lombok.RequiredArgsConstructor;
11+
import org.springframework.stereotype.Service;
12+
import org.springframework.transaction.annotation.Transactional;
13+
14+
@Service
15+
@RequiredArgsConstructor
16+
@Transactional(readOnly = true)
17+
public class UserQueryServiceImpl implements UserQueryService {
18+
19+
private final UserRepository userRepository;
20+
private final CareerRepository careerRepository;
21+
private final UserConverter userConverter;
22+
23+
@Override
24+
public UserResponseDTO.SummaryCardResponse getMySummaryCard(Long currentUserId) {
25+
User user = userRepository.findById(currentUserId)
26+
.orElseThrow(() -> new GeneralException(ErrorStatus.USER_NOT_FOUND));
27+
28+
// 재직 여부 존재 검사 (Career에 isEmployed == true 인 레코드)
29+
boolean employed = careerRepository.existsByUser_IdAndIsEmployedTrue(currentUserId);
30+
31+
return userConverter.toSummaryCardResponse(user, employed);
32+
}
33+
}
34+

0 commit comments

Comments
 (0)