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 @@ -5,7 +5,7 @@
import org.springframework.http.HttpStatus;

import static com.example.solidconnection.application.service.ApplicationSubmissionService.APPLICATION_UPDATE_COUNT_LIMIT;
import static com.example.solidconnection.siteuser.service.SiteUserService.MIN_DAYS_BETWEEN_NICKNAME_CHANGES;
import static com.example.solidconnection.siteuser.service.MyPageService.MIN_DAYS_BETWEEN_NICKNAME_CHANGES;

@Getter
@AllArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.example.solidconnection.siteuser.controller;

import com.example.solidconnection.custom.resolver.AuthorizedUser;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.dto.MyPageResponse;
import com.example.solidconnection.siteuser.service.MyPageService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RequiredArgsConstructor
@RequestMapping("/my")
@RestController
class MyPageController {

private final MyPageService myPageService;

@GetMapping
public ResponseEntity<MyPageResponse> getMyPageInfo(
@AuthorizedUser SiteUser siteUser
) {
MyPageResponse myPageResponse = myPageService.getMyPageInfo(siteUser);
return ResponseEntity.ok(myPageResponse);
}

@PatchMapping
public ResponseEntity<Void> updateMyPageInfo(
@AuthorizedUser SiteUser siteUser,
@RequestParam("file") MultipartFile imageFile,
@RequestParam("nickname") String nickname
) {
myPageService.updateMyPageInfo(siteUser, imageFile, nickname);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,26 @@
package com.example.solidconnection.siteuser.controller;

import com.example.solidconnection.custom.resolver.AuthorizedUser;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.dto.MyPageResponse;
import com.example.solidconnection.siteuser.dto.NicknameExistsResponse;
import com.example.solidconnection.siteuser.service.SiteUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RequiredArgsConstructor
@RequestMapping("/my")
@RequestMapping("/users")
@RestController
class SiteUserController {
public class SiteUserController {

private final SiteUserService siteUserService;

@GetMapping
public ResponseEntity<MyPageResponse> getMyPageInfo(
@AuthorizedUser SiteUser siteUser
@GetMapping("/exists")
public ResponseEntity<NicknameExistsResponse> checkNicknameExists(
@RequestParam("nickname") String nickname
) {
MyPageResponse myPageResponse = siteUserService.getMyPageInfo(siteUser);
return ResponseEntity.ok(myPageResponse);
}

@PatchMapping
public ResponseEntity<Void> updateMyPageInfo(
@AuthorizedUser SiteUser siteUser,
@RequestParam(value = "file", required = false) MultipartFile imageFile,
@RequestParam(value = "nickname", required = false) String nickname
) {
siteUserService.updateMyPageInfo(siteUser, imageFile, nickname);
return ResponseEntity.ok().build();
NicknameExistsResponse nicknameExistsResponse = siteUserService.checkNicknameExists(nickname);
return ResponseEntity.ok(nicknameExistsResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.solidconnection.siteuser.dto;

public record NicknameExistsResponse(
boolean exists
) {
public static NicknameExistsResponse from(boolean exists) {
return new NicknameExistsResponse(exists);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.example.solidconnection.siteuser.service;

import com.example.solidconnection.custom.exception.CustomException;
import com.example.solidconnection.s3.S3Service;
import com.example.solidconnection.s3.UploadedFileUrlResponse;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.dto.MyPageResponse;
import com.example.solidconnection.siteuser.repository.LikedUniversityRepository;
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import com.example.solidconnection.type.ImgType;
import com.example.solidconnection.university.domain.LikedUniversity;
import com.example.solidconnection.university.dto.UniversityInfoForApplyPreviewResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import static com.example.solidconnection.custom.exception.ErrorCode.CAN_NOT_CHANGE_NICKNAME_YET;
import static com.example.solidconnection.custom.exception.ErrorCode.NICKNAME_ALREADY_EXISTED;
import static com.example.solidconnection.custom.exception.ErrorCode.PROFILE_IMAGE_NEEDED;

@RequiredArgsConstructor
@Service
public class MyPageService {

public static final int MIN_DAYS_BETWEEN_NICKNAME_CHANGES = 7;
public static final DateTimeFormatter NICKNAME_LAST_CHANGE_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

private final SiteUserRepository siteUserRepository;
private final LikedUniversityRepository likedUniversityRepository;
private final S3Service s3Service;

/*
* 마이페이지 정보를 조회한다.
* */
@Transactional(readOnly = true)
public MyPageResponse getMyPageInfo(SiteUser siteUser) {
int likedUniversityCount = likedUniversityRepository.countBySiteUser_Id(siteUser.getId());
return MyPageResponse.of(siteUser, likedUniversityCount);
}

/*
* 마이페이지 정보를 수정한다.
* */
@Transactional
public void updateMyPageInfo(SiteUser siteUser, MultipartFile imageFile, String nickname) {
validateNicknameUnique(nickname);
validateNicknameNotChangedRecently(siteUser.getNicknameModifiedAt());
validateProfileImageNotEmpty(imageFile);

if (!isDefaultProfileImage(siteUser.getProfileImageUrl())) {
s3Service.deleteExProfile(siteUser);
}
UploadedFileUrlResponse uploadedFile = s3Service.uploadFile(imageFile, ImgType.PROFILE);
String profileImageUrl = uploadedFile.fileUrl();

siteUser.setProfileImageUrl(profileImageUrl);
siteUser.setNickname(nickname);
siteUser.setNicknameModifiedAt(LocalDateTime.now());
siteUserRepository.save(siteUser);
}

private void validateNicknameUnique(String nickname) {
if (siteUserRepository.existsByNickname(nickname)) {
throw new CustomException(NICKNAME_ALREADY_EXISTED);
}
}

private void validateNicknameNotChangedRecently(LocalDateTime lastModifiedAt) {
if (lastModifiedAt == null) {
return;
}
if (LocalDateTime.now().isBefore(lastModifiedAt.plusDays(MIN_DAYS_BETWEEN_NICKNAME_CHANGES))) {
String formatLastModifiedAt
= String.format("(마지막 수정 시간 : %s)", NICKNAME_LAST_CHANGE_DATE_FORMAT.format(lastModifiedAt));
throw new CustomException(CAN_NOT_CHANGE_NICKNAME_YET, formatLastModifiedAt);
}
}

private void validateProfileImageNotEmpty(MultipartFile imageFile) {
if (imageFile == null || imageFile.isEmpty()) {
throw new CustomException(PROFILE_IMAGE_NEEDED);
}
}

private boolean isDefaultProfileImage(String profileImageUrl) {
String prefix = "profile/";
return profileImageUrl == null || !profileImageUrl.startsWith(prefix);
}

/*
* 관심 대학교 목록을 조회한다.
* */
@Transactional(readOnly = true)
public List<UniversityInfoForApplyPreviewResponse> getWishUniversity(SiteUser siteUser) {
List<LikedUniversity> likedUniversities = likedUniversityRepository.findAllBySiteUser_Id(siteUser.getId());
return likedUniversities.stream()
.map(likedUniversity -> UniversityInfoForApplyPreviewResponse.from(likedUniversity.getUniversityInfoForApply()))
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,101 +1,18 @@
package com.example.solidconnection.siteuser.service;

import com.example.solidconnection.custom.exception.CustomException;
import com.example.solidconnection.s3.S3Service;
import com.example.solidconnection.s3.UploadedFileUrlResponse;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.dto.MyPageResponse;
import com.example.solidconnection.siteuser.repository.LikedUniversityRepository;
import com.example.solidconnection.siteuser.dto.NicknameExistsResponse;
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import com.example.solidconnection.type.ImgType;
import com.example.solidconnection.university.domain.LikedUniversity;
import com.example.solidconnection.university.dto.UniversityInfoForApplyPreviewResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import static com.example.solidconnection.custom.exception.ErrorCode.CAN_NOT_CHANGE_NICKNAME_YET;
import static com.example.solidconnection.custom.exception.ErrorCode.NICKNAME_ALREADY_EXISTED;
import static com.example.solidconnection.custom.exception.ErrorCode.PROFILE_IMAGE_NEEDED;

@RequiredArgsConstructor
@Service
public class SiteUserService {

public static final int MIN_DAYS_BETWEEN_NICKNAME_CHANGES = 7;
public static final DateTimeFormatter NICKNAME_LAST_CHANGE_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

private final SiteUserRepository siteUserRepository;
private final LikedUniversityRepository likedUniversityRepository;
private final S3Service s3Service;

/*
* 마이페이지 정보를 조회한다.
* */
@Transactional(readOnly = true)
public MyPageResponse getMyPageInfo(SiteUser siteUser) {
int likedUniversityCount = likedUniversityRepository.countBySiteUser_Id(siteUser.getId());
return MyPageResponse.of(siteUser, likedUniversityCount);
}

/*
* 마이페이지 정보를 수정한다.
* */
@Transactional
public void updateMyPageInfo(SiteUser siteUser, MultipartFile imageFile, String nickname) {
if (nickname != null) {
validateNicknameUnique(nickname);
validateNicknameNotChangedRecently(siteUser.getNicknameModifiedAt());
siteUser.setNickname(nickname);
siteUser.setNicknameModifiedAt(LocalDateTime.now());
}

if (imageFile != null && !imageFile.isEmpty()) {
UploadedFileUrlResponse uploadedFile = s3Service.uploadFile(imageFile, ImgType.PROFILE);
if (!isDefaultProfileImage(siteUser.getProfileImageUrl())) {
s3Service.deleteExProfile(siteUser);
}
String profileImageUrl = uploadedFile.fileUrl();
siteUser.setProfileImageUrl(profileImageUrl);
}
siteUserRepository.save(siteUser);
}

private void validateNicknameUnique(String nickname) {
if (siteUserRepository.existsByNickname(nickname)) {
throw new CustomException(NICKNAME_ALREADY_EXISTED);
}
}

private void validateNicknameNotChangedRecently(LocalDateTime lastModifiedAt) {
if (lastModifiedAt == null) {
return;
}
if (LocalDateTime.now().isBefore(lastModifiedAt.plusDays(MIN_DAYS_BETWEEN_NICKNAME_CHANGES))) {
String formatLastModifiedAt
= String.format("(마지막 수정 시간 : %s)", NICKNAME_LAST_CHANGE_DATE_FORMAT.format(lastModifiedAt));
throw new CustomException(CAN_NOT_CHANGE_NICKNAME_YET, formatLastModifiedAt);
}
}

private boolean isDefaultProfileImage(String profileImageUrl) {
String prefix = "profile/";
return profileImageUrl == null || !profileImageUrl.startsWith(prefix);
}

/*
* 관심 대학교 목록을 조회한다.
* */
@Transactional(readOnly = true)
public List<UniversityInfoForApplyPreviewResponse> getWishUniversity(SiteUser siteUser) {
List<LikedUniversity> likedUniversities = likedUniversityRepository.findAllBySiteUser_Id(siteUser.getId());
return likedUniversities.stream()
.map(likedUniversity -> UniversityInfoForApplyPreviewResponse.from(likedUniversity.getUniversityInfoForApply()))
.toList();
public NicknameExistsResponse checkNicknameExists(String nickname) {
boolean exists = siteUserRepository.existsByNickname(nickname);
return NicknameExistsResponse.from(exists);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.example.solidconnection.custom.resolver.AuthorizedUser;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.service.SiteUserService;
import com.example.solidconnection.siteuser.service.MyPageService;
import com.example.solidconnection.type.LanguageTestType;
import com.example.solidconnection.university.dto.IsLikeResponse;
import com.example.solidconnection.university.dto.LikeResultResponse;
Expand Down Expand Up @@ -32,7 +32,7 @@ public class UniversityController {
private final UniversityQueryService universityQueryService;
private final UniversityLikeService universityLikeService;
private final UniversityRecommendService universityRecommendService;
private final SiteUserService siteUserService;
private final MyPageService myPageService;

@GetMapping("/recommend")
public ResponseEntity<UniversityRecommendsResponse> getUniversityRecommends(
Expand All @@ -49,7 +49,7 @@ public ResponseEntity<UniversityRecommendsResponse> getUniversityRecommends(
public ResponseEntity<List<UniversityInfoForApplyPreviewResponse>> getMyWishUniversity(
@AuthorizedUser SiteUser siteUser
) {
List<UniversityInfoForApplyPreviewResponse> wishUniversities = siteUserService.getWishUniversity(siteUser);
List<UniversityInfoForApplyPreviewResponse> wishUniversities = myPageService.getWishUniversity(siteUser);
return ResponseEntity.ok(wishUniversities);
}

Expand Down
Loading