Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
@AllArgsConstructor
@Where(clause = "end_date >= CURRENT_DATE")
@Where(clause = "start_date <= CURRENT_DATE AND end_date >= CURRENT_DATE")
public class Partnership {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,29 @@
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ssu.eatssu.domain.partnership.entity.Partnership;
import ssu.eatssu.domain.partnership.entity.PartnershipRestaurant;
import ssu.eatssu.domain.user.department.entity.College;
import ssu.eatssu.domain.user.department.entity.Department;

import java.util.List;

public interface PartnershipRepository extends JpaRepository<Partnership, Long> {
@Query("SELECT DISTINCT p FROM Partnership p " +
"LEFT JOIN p.partnershipCollege pc " +
"LEFT JOIN p.partnershipDepartment pd " +
"WHERE (pc = :college OR pd = :department OR (pc IS NOT NULL AND pc.name = '총학'))")
List<Partnership> findRelevantPartnerships(@Param("college") College college,
@Param("department") Department department);
@Query("""
select distinct pr
from PartnershipRestaurant pr
join fetch pr.partnerships p
left join fetch p.partnershipCollege pc
left join fetch p.partnershipDepartment pd
where
(pc = :college
or pd = :department
or (pc is not null and pc.name = '총학'))
and p.startDate <= current_date
and (p.endDate is null or p.endDate >= current_date)
""")
List<PartnershipRestaurant> findRestaurantsWithMyPartnerships(
@Param("college") College college,
@Param("department") Department department
);

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import java.util.List;

public interface PartnershipRestaurantRepository extends JpaRepository<PartnershipRestaurant, Long> {
@Query("SELECT DISTINCT pr FROM PartnershipRestaurant pr " +
"LEFT JOIN FETCH pr.partnerships p " +
"LEFT JOIN FETCH p.partnershipCollege " +
"LEFT JOIN FETCH p.partnershipDepartment ")
@Query("""
SELECT DISTINCT pr FROM PartnershipRestaurant pr
LEFT JOIN FETCH pr.partnerships p
LEFT JOIN FETCH p.partnershipCollege
LEFT JOIN FETCH p.partnershipDepartment
WHERE p.startDate <= CURRENT_DATE and (p.endDate is null or p.endDate >= CURRENT_DATE)""")
List<PartnershipRestaurant> findAllWithDetails();
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,10 @@ public List<PartnershipResponse> getUserDepartmentPartnerships(CustomUserDetails
College college = department.getCollege();

return partnershipRepository
.findRelevantPartnerships(college, department)
.findRestaurantsWithMyPartnerships(college, department)
.stream()
.map(partnership -> {
PartnershipRestaurant partnershipRestaurant = partnership.getPartnershipRestaurant();

return PartnershipResponse.fromEntity(partnershipRestaurant,
customUserDetails.getId());
})
.map(partnershipRestaurant -> PartnershipResponse.fromEntity(partnershipRestaurant,
customUserDetails.getId()))
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package ssu.eatssu.domain.user.department.persistence;

import org.springframework.data.jpa.repository.JpaRepository;
import ssu.eatssu.domain.user.department.entity.College;
import ssu.eatssu.domain.user.department.entity.Department;

import java.util.List;
import java.util.Optional;

public interface DepartmentRepository extends JpaRepository<Department, Long> {
Optional<Department> findByName(String name);

List<Department> findByCollege(College college);
}
26 changes: 20 additions & 6 deletions src/main/java/ssu/eatssu/domain/user/dto/DepartmentResponse.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
package ssu.eatssu.domain.user.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Builder;
import ssu.eatssu.domain.user.department.entity.College;
import ssu.eatssu.domain.user.department.entity.Department;

@Getter
@AllArgsConstructor
public class DepartmentResponse {
private String departmentName;
@Builder
public record DepartmentResponse(
Long departmentId, String departmentName, Long collegeId, String collegeName
) {
public static DepartmentResponse from(Department department) {
if (department == null) {
return new DepartmentResponse(null, null, null, null);
}
final College college = department.getCollege();
return DepartmentResponse.builder()
.departmentId(department.getId())
.departmentName(department.getName())
.collegeId(college != null ? college.getId() : null)
.collegeName(college != null ? college.getName() : null)
.build();
}
}

10 changes: 10 additions & 0 deletions src/main/java/ssu/eatssu/domain/user/dto/GetCollegeResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ssu.eatssu.domain.user.dto;

import lombok.Builder;

@Builder
public record GetCollegeResponse(
Long id,
String name
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ssu.eatssu.domain.user.dto;

import lombok.Builder;

@Builder
public record GetDepartmentResponse(Long id,
String name) {
}
36 changes: 35 additions & 1 deletion src/main/java/ssu/eatssu/domain/user/dto/MyPageResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,49 @@
import lombok.Builder;
import lombok.Getter;
import ssu.eatssu.domain.auth.entity.OAuthProvider;
import ssu.eatssu.domain.user.department.entity.College;
import ssu.eatssu.domain.user.department.entity.Department;
import ssu.eatssu.domain.user.entity.User;

@AllArgsConstructor
@Builder
@Schema(title = "마이페이지 정보")
@Getter
public class MyPageResponse {

@Schema(description = "닉네임", example = "피치푸치")
private String nickname;

@Schema(description = "연결 계정 정보", example = "피치푸치")
@Schema(description = "연결 계정 정보", example = "GOOGLE")
private OAuthProvider provider;

@Schema(description = "학과 id", example = "1")
private Long departmentId;

@Schema(description = "학과 이름", example = "컴퓨터학부")
private String departmentName;

@Schema(description = "단과대 id", example = "1")
private Long collegeId;

@Schema(description = "단과대 이름", example = "IT 대학")
private String collegeName;

public static MyPageResponse from(User user) {
if (user == null) {
return MyPageResponse.builder().build();
}

Department department = user.getDepartment();
College college = department != null ? department.getCollege() : null;

return MyPageResponse.builder()
.nickname(user.getNickname())
.provider(user.getProvider())
.departmentId(department != null ? department.getId() : null)
.departmentName(department != null ? department.getName() : null)
.collegeId(college != null ? college.getId() : null)
.collegeName(college != null ? college.getName() : null)
.build();
Comment on lines +41 to +51

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

from 정적 팩토리 메서드 내에서 departmentcollege 객체의 null 여부를 확인하고 값을 할당하는 로직이 여러 번 반복되고 있습니다. 이 로직을 개선하여 코드의 가독성과 유지보수성을 높일 수 있습니다. if 문을 사용하여 null 체크를 한 번만 수행하고, 빌더에 값을 설정하는 방식으로 리팩토링하는 것을 제안합니다.

        MyPageResponseBuilder builder = MyPageResponse.builder()
                .nickname(user.getNickname())
                .provider(user.getProvider());

        Department department = user.getDepartment();
        if (department != null) {
            builder.departmentId(department.getId()).departmentName(department.getName());
            College college = department.getCollege();
            if (college != null) {
                builder.collegeId(college.getId()).collegeName(college.getName());
            }
        }
        return builder.build();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
@AllArgsConstructor
@NoArgsConstructor
public class UpdateDepartmentRequest {
@Schema(description = "학과 이름", example = "소프트")
private String departmentName;
@Schema(description = "학과 id", example = "1")
private Long departmentId;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@
import ssu.eatssu.domain.auth.security.CustomUserDetails;
import ssu.eatssu.domain.partnership.dto.PartnershipResponse;
import ssu.eatssu.domain.partnership.service.PartnershipService;
import ssu.eatssu.domain.review.service.ReviewServiceV2;
import ssu.eatssu.domain.slice.dto.SliceResponse;
import ssu.eatssu.domain.slice.service.SliceService;
import ssu.eatssu.domain.user.dto.DepartmentResponse;
import ssu.eatssu.domain.user.dto.GetCollegeResponse;
import ssu.eatssu.domain.user.dto.GetDepartmentResponse;
import ssu.eatssu.domain.user.dto.MyMealReviewResponse;
import ssu.eatssu.domain.user.dto.MyPageResponse;
import ssu.eatssu.domain.user.dto.MyReviewDetail;
import ssu.eatssu.domain.user.dto.NicknameUpdateRequest;
Expand All @@ -48,6 +52,7 @@ public class UserController {
private final UserService userService;
private final SliceService sliceService;
private final PartnershipService partnershipService;
private final ReviewServiceV2 reviewServiceV2;

@Operation(summary = "이메일 중복 체크", description = """
이메일 중복 체크 API 입니다.<br><br>
Expand Down Expand Up @@ -180,4 +185,42 @@ public BaseResponse<List<PartnershipResponse>> getUserDepartmentPartnerships(
public BaseResponse<DepartmentResponse> getDepartment(@AuthenticationPrincipal CustomUserDetails userDetails) {
return BaseResponse.success(userService.getDepartment(userDetails));
}

@Operation(summary = "내가 쓴 리뷰 리스트 조회", description = "내가 쓴 리뷰 리스트를 조회하는 API V2 입니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "내가 쓴 리뷰 리스트 조회 성공"),
@ApiResponse(responseCode = "404", description = "존재하지 않는 유저", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
})
@GetMapping("/v2/reviews")
public BaseResponse<SliceResponse<MyMealReviewResponse>> getMyReviews(
@Parameter(description = "마지막으로 조회된 reviewId값(첫 조회시 값 필요 없음)", in = ParameterIn.QUERY) @RequestParam(required = false) Long lastReviewId,
@ParameterObject @PageableDefault(size = 20, sort = "date", direction = Sort.Direction.DESC) Pageable pageable,
@AuthenticationPrincipal CustomUserDetails customUserDetails) {
SliceResponse<MyMealReviewResponse> myReviews = reviewServiceV2.findMyReviews(customUserDetails,
lastReviewId,
pageable);
return BaseResponse.success(myReviews);
}

@Operation(summary = "단과대 조회", description = "숭실대학교 단과대학 들을 조회하는 API입니다.(토큰 불필요)")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "단과대 리스트 조회 성공"),
@ApiResponse(responseCode = "404", description = "존재하지 않는 단과대", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
})
@GetMapping("/lookup/colleges")
public BaseResponse<List<GetCollegeResponse>> getColleges() {
List<GetCollegeResponse> getCollegeResponses = userService.getCollegeList();
return BaseResponse.success(getCollegeResponses);
}

@Operation(summary = "단과대에 따른 학과 조회", description = "단과대학을 입력하면 단과대에 속한 숭실대학교 학과를 조회하는 API입니다.(토큰 불필요)")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "단과대 리스트 조회 성공"),
})
@GetMapping("/lookup/departments")
public BaseResponse<List<GetDepartmentResponse>> getDepartments(@RequestParam Long collegeId) {
List<GetDepartmentResponse> getCollegeResponses = userService.getDepartmentList(collegeId);
return BaseResponse.success(getCollegeResponses);
Comment on lines +222 to +223

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

getDepartments 메서드 내에서 userService.getDepartmentList(collegeId)의 반환 값을 getCollegeResponses라는 변수에 할당하고 있습니다. 이 변수명은 메서드의 기능과 반환되는 데이터의 타입(List<GetDepartmentResponse>)을 정확하게 반영하지 못하여 혼동을 줄 수 있습니다. 변수명을 getDepartmentResponses로 변경하여 코드의 명확성을 높이는 것을 권장합니다.

Suggested change
List<GetDepartmentResponse> getCollegeResponses = userService.getDepartmentList(collegeId);
return BaseResponse.success(getCollegeResponses);
List<GetDepartmentResponse> getDepartmentResponses = userService.getDepartmentList(collegeId);
return BaseResponse.success(getDepartmentResponses);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);

Optional<User> findByProviderId(String providerId);

Optional<User> findByNickname(String nickname);
}
34 changes: 30 additions & 4 deletions src/main/java/ssu/eatssu/domain/user/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,27 @@
import ssu.eatssu.domain.auth.security.CustomUserDetails;
import ssu.eatssu.domain.review.entity.Review;
import ssu.eatssu.domain.user.config.UserProperties;
import ssu.eatssu.domain.user.department.entity.College;
import ssu.eatssu.domain.user.department.entity.Department;
import ssu.eatssu.domain.user.department.persistence.CollegeRepository;
import ssu.eatssu.domain.user.department.persistence.DepartmentRepository;
import ssu.eatssu.domain.user.dto.DepartmentResponse;
import ssu.eatssu.domain.user.dto.GetCollegeResponse;
import ssu.eatssu.domain.user.dto.GetDepartmentResponse;
import ssu.eatssu.domain.user.dto.MyPageResponse;
import ssu.eatssu.domain.user.dto.NicknameUpdateRequest;
import ssu.eatssu.domain.user.dto.UpdateDepartmentRequest;
import ssu.eatssu.domain.user.entity.User;
import ssu.eatssu.domain.user.repository.UserRepository;
import ssu.eatssu.global.handler.response.BaseException;

import java.util.List;
import java.util.UUID;

import static ssu.eatssu.global.handler.response.BaseResponseStatus.DUPLICATE_NICKNAME;
import static ssu.eatssu.global.handler.response.BaseResponseStatus.NOT_FOUND_DEPARTMENT;
import static ssu.eatssu.global.handler.response.BaseResponseStatus.NOT_FOUND_USER;
import static ssu.eatssu.global.handler.response.BaseResponseStatus.VALIDATION_ERROR;

@Slf4j
@Service
Expand All @@ -37,6 +43,7 @@ public class UserService {
private final PasswordEncoder passwordEncoder;
private final DepartmentRepository departmentRepository;
private final UserProperties userProperties;
private final CollegeRepository collegeRepository;

public User join(String email, OAuthProvider provider, String providerId) {
String credentials = createCredentials(provider, providerId);
Expand All @@ -59,7 +66,7 @@ public void updateNickname(CustomUserDetails userDetails, NicknameUpdateRequest
public MyPageResponse findMyPage(CustomUserDetails userDetails) {
User user = userRepository.findById(userDetails.getId())
.orElseThrow(() -> new BaseException(NOT_FOUND_USER));
return new MyPageResponse(user.getNickname(), user.getProvider());
return MyPageResponse.from(user);
}

public boolean withdraw(CustomUserDetails userDetails) {
Expand Down Expand Up @@ -98,7 +105,7 @@ private String createCredentials(OAuthProvider provider, String providerId) {
public void registerDepartment(UpdateDepartmentRequest request, CustomUserDetails userDetails) {
User user = userRepository.findById(userDetails.getId())
.orElseThrow(() -> new BaseException(NOT_FOUND_USER));
Department department = departmentRepository.findByName(request.getDepartmentName())
Department department = departmentRepository.findById(request.getDepartmentId())
.orElseThrow(() -> new BaseException(NOT_FOUND_DEPARTMENT));

user.updateDepartment(department);
Expand All @@ -107,8 +114,27 @@ public void registerDepartment(UpdateDepartmentRequest request, CustomUserDetail
public DepartmentResponse getDepartment(CustomUserDetails userDetails) {
User user = userRepository.findById(userDetails.getId())
.orElseThrow(() -> new BaseException(NOT_FOUND_USER));
Department department = user.getDepartment();
return new DepartmentResponse(department != null ? department.getName() : "");
return DepartmentResponse.from(user.getDepartment());
}

public List<GetCollegeResponse> getCollegeList() {
List<College> colleges = collegeRepository.findAll();
return colleges.stream().map(college -> GetCollegeResponse.builder()
.id(college.getId())
.name(college.getName())
.build())
.toList();
Comment on lines +122 to +126

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

getCollegeList 메서드에서 stream().map()을 사용하여 GetCollegeResponse 객체를 생성할 때 빌더 패턴을 사용하고 있습니다. GetCollegeResponserecord 타입이므로, 빌더 대신 생성자를 직접 호출하는 것이 더 간결하고 효율적입니다.

        return colleges.stream().map(college -> new GetCollegeResponse(college.getId(), college.getName()))
                       .toList();

}

public List<GetDepartmentResponse> getDepartmentList(Long collegeId) {
College college = collegeRepository.findById(collegeId)
.orElseThrow(() -> new BaseException(VALIDATION_ERROR));
Comment on lines +130 to +131

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

getDepartmentList 메서드에서 collegeIdCollege를 찾지 못했을 때 VALIDATION_ERROR 예외를 발생시키고 있습니다. 이는 "입력값 유효성 검사 오류"를 의미하는 일반적인 예외로, "해당 단과대를 찾을 수 없음"이라는 더 구체적인 상황을 표현하기에는 부족합니다. BaseResponseStatus에 정의된 NOT_FOUND_COLLEGE를 사용하여 더 명확하고 의미 있는 예외 처리를 하는 것이 좋습니다.

        College college = collegeRepository.findById(collegeId)
                                           .orElseThrow(() -> new BaseException(NOT_FOUND_COLLEGE));

List<Department> departments = departmentRepository.findByCollege(college);
return departments.stream().map(department -> GetDepartmentResponse.builder()
.id(department.getId())
.name(department.getName())
.build())
.toList();
Comment on lines +133 to +137

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

getDepartmentList 메서드에서 stream().map()을 사용하여 GetDepartmentResponse 객체를 생성할 때 빌더 패턴을 사용하고 있습니다. GetDepartmentResponserecord 타입이므로, 빌더 대신 생성자를 직접 호출하는 것이 더 간결하고 효율적입니다.

        return departments.stream().map(department -> new GetDepartmentResponse(department.getId(), department.getName()))
                       .toList();

}

private boolean isForbiddenNickname(String nickname) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public enum BaseResponseStatus {
NOT_FOUND_DEPARTMENT(false, HttpStatus.NOT_FOUND, 40409, "해당 학과를 찾을 수 없습니다."),
NOT_FOUND_PARTNERSHIP(false, HttpStatus.NOT_FOUND, 40410, "해당 제휴를 찾을 수 없습니다."),
NOT_FOUND_PARTNERSHIP_RESTAURANT(false, HttpStatus.NOT_FOUND, 40411, "해당 제휴 식당을 찾을 수 없습니다."),
INVALID_NICKNAME(false,HttpStatus.NOT_FOUND,40412,"잘못된 닉네임입니다."),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

새로 추가된 INVALID_NICKNAME 상태의 HTTP 상태 코드가 HttpStatus.NOT_FOUND (404)로 설정되어 있습니다. "잘못된 닉네임"은 클라이언트의 요청 값이 유효하지 않다는 의미이므로, "리소스를 찾을 수 없음"을 의미하는 404보다는 "잘못된 요청"을 의미하는 HttpStatus.BAD_REQUEST (400)가 더 적절해 보입니다.

Suggested change
INVALID_NICKNAME(false,HttpStatus.NOT_FOUND,40412,"잘못된 닉네임입니다."),
INVALID_NICKNAME(false,HttpStatus.BAD_REQUEST,40412,"잘못된 닉네임입니다."),


/**
* 405 METHOD_NOT_ALLOWED 지원하지 않은 method 호출
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ spring:
jwt:
secret:
key: ${EATSSU_JWT_SECRET_DEV}
token-validity-in-seconds: 60
refresh-token-validity-in-seconds: 180
token-validity-in-seconds: 86400
refresh-token-validity-in-seconds: 604800

#S3
cloud:
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ spring:
jwt:
secret:
key: ${EATSSU_JWT_SECRET_LOCAL}
token-validity-in-seconds: 10
refresh-token-validity-in-seconds: 30
token-validity-in-seconds: 86400
refresh-token-validity-in-seconds: 604800

cloud:
aws:
Expand Down