diff --git a/src/main/java/com/fledge/fledgeserver/auth/dto/OAuth2UserInfo.java b/src/main/java/com/fledge/fledgeserver/auth/dto/OAuth2UserInfo.java deleted file mode 100644 index 84add26..0000000 --- a/src/main/java/com/fledge/fledgeserver/auth/dto/OAuth2UserInfo.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.fledge.fledgeserver.auth.dto; - -import java.util.Map; - -import com.fledge.fledgeserver.exception.AuthException; -import com.fledge.fledgeserver.member.entity.Member; -import com.fledge.fledgeserver.member.entity.Role; -import lombok.Builder; - -import static com.fledge.fledgeserver.exception.ErrorCode.ILLEGAL_REGISTRATION_ID; - -@Builder -public record OAuth2UserInfo( - String nickname, - String registerType, - String email, - String profile, - Long socialId -) { - - public static OAuth2UserInfo of(String registrationId, Map attributes) { - return switch (registrationId) { - case "kakao" -> ofKakao(attributes); - default -> throw new AuthException(ILLEGAL_REGISTRATION_ID); - }; - } - - private static OAuth2UserInfo ofKakao(Map attributes) { - - Map account = (Map) attributes.get("kakao_account"); - Map profile = (Map) account.get("profile"); - - - return OAuth2UserInfo.builder() - .socialId((Long) attributes.get("id")) - .nickname((String) profile.get("nickname")) - .email((String) account.get("email")) - .profile((String) profile.get("profile_image_url")) - .registerType("KAKAO") - .build(); - } - - public Member toEntity() { - return Member.builder() - .socialId(socialId) - .nickname(nickname) - .email(email) - .profile(profile) - .role(Role.USER) - .registerType("KAKAO") - .build(); - } -} diff --git a/src/main/java/com/fledge/fledgeserver/auth/dto/OAuthAttributes.java b/src/main/java/com/fledge/fledgeserver/auth/dto/OAuthAttributes.java new file mode 100644 index 0000000..90a36f8 --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/auth/dto/OAuthAttributes.java @@ -0,0 +1,73 @@ +package com.fledge.fledgeserver.auth.dto; + +import com.fledge.fledgeserver.exception.AuthException; +import com.fledge.fledgeserver.member.entity.Member; +import com.fledge.fledgeserver.member.entity.Role; +import lombok.Builder; +import lombok.Getter; + +import java.util.Map; +import java.util.UUID; + +import static com.fledge.fledgeserver.exception.ErrorCode.ILLEGAL_REGISTRATION_ID; + +@Getter +public class OAuthAttributes { + private final Map attributes; + private final String nameAttributeKey; + private final String nickname; + private final String email; + private final String profile; + private final String registerType; + private final Long socialId; + + @Builder + public OAuthAttributes(Map attributes, String nameAttributeKey, String nickname, String email, String profile, String registerType, Long socialId) { + this.attributes = attributes; + this.nameAttributeKey = nameAttributeKey; + this.nickname = nickname; + this.email = email; + this.profile = profile; + this.registerType = registerType; + this.socialId = socialId; + } + + public static OAuthAttributes of(String socialName, String userNameAttributeName, Map attributes) { + + if ("kakao".equals(socialName)) { + return ofKakao(userNameAttributeName, attributes); + } + + throw new AuthException(ILLEGAL_REGISTRATION_ID); + } + + private static OAuthAttributes ofKakao(String userNameAttributeName, Map attributes) { + Map account = (Map) attributes.get("kakao_account"); + Map profile = (Map) account.get("profile"); + + return OAuthAttributes.builder() + .nameAttributeKey(userNameAttributeName) + .attributes(attributes) + .socialId(Long.valueOf(attributes.get("id").toString())) + .nickname((String) profile.get("nickname")) + .email((String) account.get("email")) + .profile((String) profile.get("profile_image_url")) + .registerType("KAKAO") + .build(); + } + + public Member toEntity() { + return Member.builder() + .socialId(socialId) + .nickname(generateRandomNickname()) + .email(email) + .profile(profile) + .role(Role.USER) + .registerType("KAKAO") + .build(); + } + + private static String generateRandomNickname() { + return "User_" + UUID.randomUUID().toString().replace("-", "").substring(0, 8); + } +} diff --git a/src/main/java/com/fledge/fledgeserver/auth/dto/OAuthUserImpl.java b/src/main/java/com/fledge/fledgeserver/auth/dto/OAuthUserImpl.java new file mode 100644 index 0000000..2a0d1a6 --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/auth/dto/OAuthUserImpl.java @@ -0,0 +1,58 @@ +package com.fledge.fledgeserver.auth.dto; + +import com.fledge.fledgeserver.member.entity.Member; +import lombok.Getter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.user.DefaultOAuth2User; + +import java.util.Collection; +import java.util.Map; + +@Getter +public class OAuthUserImpl extends DefaultOAuth2User implements UserDetails { + private final Member member; + + public OAuthUserImpl(Collection authorities, + Map attributes, + String nameAttributeKey, + Member member) { + super(authorities, attributes, nameAttributeKey); + this.member = member; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return member.getId().toString(); + } + + @Override + public boolean isAccountNonExpired() { + return member.isActive(); + } + + @Override + public boolean isAccountNonLocked() { + return member.isActive(); + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return member.isActive(); + } + + public Member getMember() { + return member; + } + +} \ No newline at end of file diff --git a/src/main/java/com/fledge/fledgeserver/auth/dto/PrincipalDetails.java b/src/main/java/com/fledge/fledgeserver/auth/dto/PrincipalDetails.java deleted file mode 100644 index 3831e17..0000000 --- a/src/main/java/com/fledge/fledgeserver/auth/dto/PrincipalDetails.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.fledge.fledgeserver.auth.dto; - -import com.fledge.fledgeserver.member.entity.Member; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.oauth2.core.user.OAuth2User; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - -public record PrincipalDetails( - Member member, - Map attributes, - String attributeKey) implements OAuth2User, UserDetails { - - @Override - public String getName() { - return attributes.get(attributeKey).toString(); - } - - @Override - public Map getAttributes() { - return attributes; - } - - @Override - public Collection getAuthorities() { - return Collections.singletonList( - new SimpleGrantedAuthority(member.getRole().getKey())); - } - - @Override - public String getPassword() { - return null; - } - - @Override - public String getUsername() { - return member.getEmail(); - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return true; - } -} \ No newline at end of file diff --git a/src/main/java/com/fledge/fledgeserver/auth/jwt/TokenProvider.java b/src/main/java/com/fledge/fledgeserver/auth/jwt/TokenProvider.java index d312df2..4cd942a 100644 --- a/src/main/java/com/fledge/fledgeserver/auth/jwt/TokenProvider.java +++ b/src/main/java/com/fledge/fledgeserver/auth/jwt/TokenProvider.java @@ -1,5 +1,6 @@ package com.fledge.fledgeserver.auth.jwt; +import com.fledge.fledgeserver.auth.service.CustomUserDetailsService; import com.fledge.fledgeserver.auth.service.TokenService; import com.fledge.fledgeserver.exception.TokenException; import io.jsonwebtoken.Claims; @@ -21,6 +22,8 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; @@ -42,6 +45,7 @@ public class TokenProvider { private static final String KEY_ROLE = "role"; private final TokenService tokenService; + private final CustomUserDetailsService userDetailsService; @PostConstruct private void setSecretKey() { @@ -78,8 +82,9 @@ public Authentication getAuthentication(String token) { Claims claims = parseClaims(token); List authorities = getAuthorities(claims); - User principal = new User(claims.getSubject(), "", authorities); - return new UsernamePasswordAuthenticationToken(principal, token, authorities); + UserDetails userDetails = userDetailsService.loadUserByUsername( + claims.getSubject()); + return new UsernamePasswordAuthenticationToken(userDetails, token, authorities); } private List getAuthorities(Claims claims) { diff --git a/src/main/java/com/fledge/fledgeserver/auth/service/CustomOAuth2UserService.java b/src/main/java/com/fledge/fledgeserver/auth/service/CustomOAuth2UserService.java index 4120aa3..2462a90 100644 --- a/src/main/java/com/fledge/fledgeserver/auth/service/CustomOAuth2UserService.java +++ b/src/main/java/com/fledge/fledgeserver/auth/service/CustomOAuth2UserService.java @@ -1,12 +1,14 @@ package com.fledge.fledgeserver.auth.service; +import java.util.Collections; import java.util.Map; +import com.fledge.fledgeserver.auth.dto.OAuthUserImpl; +import com.fledge.fledgeserver.auth.dto.OAuthAttributes; import com.fledge.fledgeserver.member.entity.Member; import com.fledge.fledgeserver.member.repository.MemberRepository; -import com.fledge.fledgeserver.auth.dto.OAuth2UserInfo; -import com.fledge.fledgeserver.auth.dto.PrincipalDetails; import lombok.RequiredArgsConstructor; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; @@ -28,15 +30,16 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails() .getUserInfoEndpoint().getUserNameAttributeName(); - OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfo.of(registrationId, oAuth2UserAttributes); - Member member = getOrSave(oAuth2UserInfo); + OAuthAttributes oauthAttributes = OAuthAttributes.of(registrationId, userNameAttributeName, oAuth2UserAttributes); + Member member = getOrSave(oauthAttributes); - return new PrincipalDetails(member, oAuth2UserAttributes, userNameAttributeName); + return new OAuthUserImpl(Collections.singleton(new SimpleGrantedAuthority(member.getRole().getKey())), + oAuth2UserAttributes, oauthAttributes.getNameAttributeKey(), member); } - private Member getOrSave(OAuth2UserInfo oAuth2UserInfo) { - Member member = memberRepository.findBySocialId(oAuth2UserInfo.socialId()) - .orElseGet(oAuth2UserInfo::toEntity); + private Member getOrSave(OAuthAttributes oauth2Attributes) { + Member member = memberRepository.findBySocialId(oauth2Attributes.getSocialId()) + .orElseGet(oauth2Attributes::toEntity); return memberRepository.save(member); } } \ No newline at end of file diff --git a/src/main/java/com/fledge/fledgeserver/auth/service/CustomUserDetailsService.java b/src/main/java/com/fledge/fledgeserver/auth/service/CustomUserDetailsService.java new file mode 100644 index 0000000..5f06c5f --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/auth/service/CustomUserDetailsService.java @@ -0,0 +1,45 @@ +package com.fledge.fledgeserver.auth.service; + +import com.fledge.fledgeserver.auth.dto.OAuthUserImpl; +import com.fledge.fledgeserver.member.entity.Member; +import com.fledge.fledgeserver.member.repository.MemberRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@Service +@RequiredArgsConstructor +public class CustomUserDetailsService implements UserDetailsService { + private final MemberRepository memberRepository; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + Member member = memberRepository.findById(Long.valueOf(username)) + .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다: " + username)); + + return new OAuthUserImpl( + Collections.singleton(new SimpleGrantedAuthority(member.getRole().name())), + createAttributes(member), + "email", + member + ); + } + + // TODO :: Method 분리 + private Map createAttributes(Member member) { + Map attributes = new HashMap<>(); + attributes.put("socialId", member.getSocialId()); + attributes.put("nickname", member.getNickname()); + attributes.put("email", member.getEmail()); + attributes.put("profile", member.getProfile()); + attributes.put("registerType", member.getRegisterType()); + return attributes; + } +} \ No newline at end of file diff --git a/src/main/java/com/fledge/fledgeserver/canary/controller/CanaryProfileController.java b/src/main/java/com/fledge/fledgeserver/canary/controller/CanaryProfileController.java index 8b2c5b6..82383fa 100644 --- a/src/main/java/com/fledge/fledgeserver/canary/controller/CanaryProfileController.java +++ b/src/main/java/com/fledge/fledgeserver/canary/controller/CanaryProfileController.java @@ -1,23 +1,28 @@ package com.fledge.fledgeserver.canary.controller; -import com.fledge.fledgeserver.canary.dto.CanaryProfileRequest; -import com.fledge.fledgeserver.canary.dto.CanaryProfileResponse; -import com.fledge.fledgeserver.canary.dto.CanaryProfileUpdateRequest; +import com.fledge.fledgeserver.auth.dto.OAuthUserImpl; +import com.fledge.fledgeserver.canary.dto.*; import com.fledge.fledgeserver.canary.service.CanaryProfileService; +import com.fledge.fledgeserver.common.utils.SecurityUtils; +import com.fledge.fledgeserver.member.entity.Member; import com.fledge.fledgeserver.response.ApiResponse; import com.fledge.fledgeserver.response.SuccessStatus; +import com.fledge.fledgeserver.support.dto.response.SupportGetResponseDto; import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import java.security.Principal; + +import static com.fledge.fledgeserver.response.SuccessStatus.GET_SUPPORT_SUCCESS; + @Tag(name = "자립준비청년 API", description = "자립준비청년 관리 관련 API") @RestController @RequiredArgsConstructor @@ -34,8 +39,8 @@ public class CanaryProfileController { @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "409", description = "이미 신청한 유저") }) public ResponseEntity> applyForCanaryProfile(@Valid @RequestBody CanaryProfileRequest request, - @AuthenticationPrincipal UserDetails userDetails) { - canaryProfileService.createCanaryProfile(request, userDetails.getUsername()); + @AuthenticationPrincipal OAuthUserImpl oAuth2User) { + canaryProfileService.createCanaryProfile(request, oAuth2User); return ApiResponse.success(SuccessStatus.PROFILE_APPLICATION_SUCCESS); } @@ -43,8 +48,8 @@ public ResponseEntity> applyForCanaryProfile(@Valid @RequestBo @GetMapping("/{userId}/status") public ResponseEntity> getApprovalStatus( @Parameter(description = "사용자 ID", required = true, example = "1") @PathVariable Long userId, - @AuthenticationPrincipal UserDetails userDetails) { - int status = canaryProfileService.getApprovalStatus(userId, userDetails.getUsername()); + @AuthenticationPrincipal OAuthUserImpl oAuth2User) { + int status = canaryProfileService.getApprovalStatus(userId, oAuth2User); return ApiResponse.success(SuccessStatus.PROFILE_RETRIEVAL_SUCCESS, status); } @@ -61,8 +66,32 @@ public ResponseEntity> getCanaryProfile( public ResponseEntity> updateCanaryProfile( @Parameter(description = "사용자 ID", required = true, example = "1") @PathVariable Long userId, @Valid @RequestBody CanaryProfileUpdateRequest request, - @AuthenticationPrincipal UserDetails userDetails) { - CanaryProfileResponse response = canaryProfileService.updateCanaryProfile(userId, request, userDetails.getUsername()); + @AuthenticationPrincipal OAuthUserImpl oAuth2User) { + CanaryProfileResponse response = canaryProfileService.updateCanaryProfile(userId, request, oAuth2User); return ApiResponse.success(SuccessStatus.PROFILE_UPDATE_SUCCESS, response); } + + /** + * 이하 API 후원하기 시에 필요 + */ + + @Operation(summary = "자립준비청년 배송지 정보 조회", description = "자립준비청년 후원글 작성 시 배송지 정보를 불러올 수 있습니다.") + @GetMapping("/delivery") + public ResponseEntity> getCanaryDeliveryInfo( + Principal principal + ) + { + Long memberId = SecurityUtils.getCurrentUserId(principal); + System.out.println("memberId = " + memberId); + return ApiResponse.success(SuccessStatus.DELIVERY_INFO_GET_SUCCESS, canaryProfileService.getCanaryDeliveryInfo(memberId)); + } + + @Operation(summary = "후원하기 게시글 조회 시 자립준비청년 프로필 조회", description = "후원하기 게시글에서 자립준비청년 프로필을 조회합니다.") + @GetMapping("/{memberId}/supports") + public ResponseEntity> getSupport( + @PathVariable(value = "memberId") Long memberId + ) { + // TODO :: 자립준비청년이 완료한 챌린지 및 후원 인증 스토리 그리고 인증률도 함께 보여줘야함! + return ApiResponse.success(GET_SUPPORT_SUCCESS, canaryProfileService.getCanaryForSupport(memberId)); + } } \ No newline at end of file diff --git a/src/main/java/com/fledge/fledgeserver/canary/dto/CanaryGetDeliveryInfoResponse.java b/src/main/java/com/fledge/fledgeserver/canary/dto/CanaryGetDeliveryInfoResponse.java new file mode 100644 index 0000000..cd83b83 --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/canary/dto/CanaryGetDeliveryInfoResponse.java @@ -0,0 +1,35 @@ +package com.fledge.fledgeserver.canary.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Getter; + +@Getter +@Schema(description = "자립준비청년 배송지 정보 조회 응답 DTO") +public class CanaryGetDeliveryInfoResponse { + + @Schema(description = "실명", example = "홍길동") + private String name; + + @Schema(description = "거주지", example = "서울특별시 강남구 역삼동") + private String address; + + @Schema(description = "상세 주소", example = "123-45") + private String detailAddress; + + @Schema(description = "우편번호", example = "12345") + private String zip; + + @Schema(description = "전화번호", example = "010-1234-5678") + private String phone; + + + public CanaryGetDeliveryInfoResponse(String name, String address, String detailAddress, String zip, String phone) { + this.name = name; + this.address = address; + this.detailAddress = detailAddress; + this.zip = zip; + this.phone = phone; + } +} diff --git a/src/main/java/com/fledge/fledgeserver/canary/dto/CanaryProfileGetResponseDto.java b/src/main/java/com/fledge/fledgeserver/canary/dto/CanaryProfileGetResponseDto.java new file mode 100644 index 0000000..46b9586 --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/canary/dto/CanaryProfileGetResponseDto.java @@ -0,0 +1,25 @@ +package com.fledge.fledgeserver.canary.dto; + +import com.fledge.fledgeserver.canary.entity.CanaryProfile; +import com.fledge.fledgeserver.member.entity.Member; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +import java.util.Date; + +@Getter +@Schema(description = "후원하기에서 자립준비청년 프로필 조회 응답 DTO") +public class CanaryProfileGetResponseDto { + + @Schema(description = "닉네임", example = "카드값줘체리") + private String nickname; + + @Schema(description = "자기 소개", example = "안녕하세요, 저는...") + private String introduction; + + + public CanaryProfileGetResponseDto(CanaryProfile canaryProfile) { + this.nickname = canaryProfile.getMember().getNickname(); + this.introduction = canaryProfile.getIntroduction(); + } +} diff --git a/src/main/java/com/fledge/fledgeserver/canary/dto/CanaryProfileUpdateRequest.java b/src/main/java/com/fledge/fledgeserver/canary/dto/CanaryProfileUpdateRequest.java index 6dd9e1f..685bb46 100644 --- a/src/main/java/com/fledge/fledgeserver/canary/dto/CanaryProfileUpdateRequest.java +++ b/src/main/java/com/fledge/fledgeserver/canary/dto/CanaryProfileUpdateRequest.java @@ -15,6 +15,11 @@ @Schema(description = "자립준비청년 프로필 수정 요청 DTO") public class CanaryProfileUpdateRequest { + @Schema(description = "실명", required = true, example = "홍길동") + @NotBlank(message = "실명은 필수입니다.") + @Size(max = 10, message = "실명은 최대 10자까지 입력 가능합니다.") + private String name; + @Schema(description = "전화번호", required = true, example = "010-1234-5678") @NotBlank(message = "전화번호는 필수입니다.") @Size(max = 20, message = "전화번호는 최대 20자까지 입력 가능합니다.") diff --git a/src/main/java/com/fledge/fledgeserver/canary/entity/CanaryProfile.java b/src/main/java/com/fledge/fledgeserver/canary/entity/CanaryProfile.java index 0811739..455eec1 100644 --- a/src/main/java/com/fledge/fledgeserver/canary/entity/CanaryProfile.java +++ b/src/main/java/com/fledge/fledgeserver/canary/entity/CanaryProfile.java @@ -24,6 +24,9 @@ public class CanaryProfile extends BaseTimeEntity { @JoinColumn(name = "fk_user_id", nullable = false) private Member member; + @Column(nullable = false) + private String name; + @Column(nullable = false) private String phone; @@ -62,10 +65,11 @@ public class CanaryProfile extends BaseTimeEntity { private Double longitude; @Builder - public CanaryProfile(Member member, String phone, Date birth, Boolean gender, String address, String detailAddress, + public CanaryProfile(Member member, String name, String phone, Date birth, Boolean gender, String address, String detailAddress, String zip, String certificateFilePath, String interestArea, Boolean approvalStatus, Double latitude, Double longitude) { this.member = member; + this.name = name; this.phone = phone; this.birth = birth; this.gender = gender; @@ -81,6 +85,7 @@ public CanaryProfile(Member member, String phone, Date birth, Boolean gender, St } public void update(CanaryProfileUpdateRequest request) { + this.name = request.getName(); this.phone = request.getPhone(); this.birth = request.getBirth(); this.gender = request.getGender(); diff --git a/src/main/java/com/fledge/fledgeserver/canary/repository/CanaryProfileRepository.java b/src/main/java/com/fledge/fledgeserver/canary/repository/CanaryProfileRepository.java index b4733e8..23b820c 100644 --- a/src/main/java/com/fledge/fledgeserver/canary/repository/CanaryProfileRepository.java +++ b/src/main/java/com/fledge/fledgeserver/canary/repository/CanaryProfileRepository.java @@ -10,4 +10,6 @@ public interface CanaryProfileRepository extends JpaRepository findByMemberId(Long memberId); + + Optional findCanaryProfileByMemberId(Long memberId); } diff --git a/src/main/java/com/fledge/fledgeserver/canary/service/CanaryProfileService.java b/src/main/java/com/fledge/fledgeserver/canary/service/CanaryProfileService.java index 8300e4c..b52b0b1 100644 --- a/src/main/java/com/fledge/fledgeserver/canary/service/CanaryProfileService.java +++ b/src/main/java/com/fledge/fledgeserver/canary/service/CanaryProfileService.java @@ -1,20 +1,18 @@ package com.fledge.fledgeserver.canary.service; -import com.fledge.fledgeserver.canary.dto.CanaryProfileRequest; -import com.fledge.fledgeserver.canary.dto.CanaryProfileResponse; -import com.fledge.fledgeserver.canary.dto.CanaryProfileUpdateRequest; +import com.fledge.fledgeserver.auth.dto.OAuthUserImpl; +import com.fledge.fledgeserver.canary.dto.*; import com.fledge.fledgeserver.canary.entity.CanaryProfile; import com.fledge.fledgeserver.canary.repository.CanaryProfileRepository; +import com.fledge.fledgeserver.common.utils.SecurityUtils; import com.fledge.fledgeserver.exception.CustomException; import com.fledge.fledgeserver.exception.ErrorCode; import com.fledge.fledgeserver.member.entity.Member; -import com.fledge.fledgeserver.member.repository.MemberRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import static com.fledge.fledgeserver.exception.ErrorCode.MEMBER_FORBIDDEN; -import static com.fledge.fledgeserver.exception.ErrorCode.MEMBER_NOT_FOUND; @Service @@ -22,11 +20,10 @@ public class CanaryProfileService { private final CanaryProfileRepository canaryProfileRepository; - private final MemberRepository memberRepository; @Transactional - public void createCanaryProfile(CanaryProfileRequest request, String currentUserEmail) { - Member member = authenticateAndAuthorize(currentUserEmail, request.getUserId()); + public void createCanaryProfile(CanaryProfileRequest request, OAuthUserImpl oAuth2User) { + Member member = authenticateAndAuthorize(oAuth2User, request.getUserId()); boolean exists = canaryProfileRepository.existsByMember(member); if (exists) { @@ -51,8 +48,8 @@ public void createCanaryProfile(CanaryProfileRequest request, String currentUser } @Transactional(readOnly = true) - public int getApprovalStatus(Long userId, String currentUserEmail) { - authenticateAndAuthorize(currentUserEmail, userId); + public int getApprovalStatus(Long userId, OAuthUserImpl oAuth2User) { + authenticateAndAuthorize(oAuth2User, userId); CanaryProfile canaryProfile = canaryProfileRepository.findByMemberId(userId) .orElse(null); @@ -75,8 +72,8 @@ public CanaryProfileResponse getCanaryProfile(Long userId) { } @Transactional - public CanaryProfileResponse updateCanaryProfile(Long userId, CanaryProfileUpdateRequest request, String currentUserEmail) { - authenticateAndAuthorize(currentUserEmail, userId); + public CanaryProfileResponse updateCanaryProfile(Long userId, CanaryProfileUpdateRequest request, OAuthUserImpl oAuth2User) { + authenticateAndAuthorize(oAuth2User, userId); CanaryProfile existingProfile = canaryProfileRepository.findByMemberId(userId) .orElseThrow(() -> new CustomException(ErrorCode.CANARY_NOT_FOUND)); @@ -89,9 +86,8 @@ public CanaryProfileResponse updateCanaryProfile(Long userId, CanaryProfileUpdat } - private Member authenticateAndAuthorize(String currentUserEmail, Long userId) { - Member member = memberRepository.findByEmailAndActiveTrue(currentUserEmail) - .orElseThrow(() -> new CustomException(MEMBER_NOT_FOUND)); + private Member authenticateAndAuthorize(OAuthUserImpl oAuth2User, Long userId) { + Member member = SecurityUtils.getCurrentMember(oAuth2User); if (member.getId() != userId) { throw new CustomException(MEMBER_FORBIDDEN); @@ -99,4 +95,25 @@ private Member authenticateAndAuthorize(String currentUserEmail, Long userId) { return member; } + + @Transactional(readOnly = true) + public CanaryGetDeliveryInfoResponse getCanaryDeliveryInfo(Long userId) { + CanaryProfile canary = canaryProfileRepository.findCanaryProfileByMemberId(userId) + .orElseThrow(() -> new CustomException(ErrorCode.CANARY_NOT_FOUND)); + return new CanaryGetDeliveryInfoResponse( + canary.getName(), + canary.getAddress(), + canary.getDetailAddress(), + canary.getZip(), + canary.getPhone() + ); + } + + @Transactional(readOnly = true) + public CanaryProfileGetResponseDto getCanaryForSupport(Long memberId) { + CanaryProfile canaryProfile = canaryProfileRepository.findByMemberId(memberId) + .orElseThrow(() -> new CustomException(ErrorCode.CANARY_NOT_FOUND)); + + return new CanaryProfileGetResponseDto(canaryProfile); + } } \ No newline at end of file diff --git a/src/main/java/com/fledge/fledgeserver/common/utils/SecurityUtils.java b/src/main/java/com/fledge/fledgeserver/common/utils/SecurityUtils.java new file mode 100644 index 0000000..91f54df --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/common/utils/SecurityUtils.java @@ -0,0 +1,71 @@ +package com.fledge.fledgeserver.common.utils; + +import com.fledge.fledgeserver.auth.dto.OAuthUserImpl; +import com.fledge.fledgeserver.exception.CustomException; +import com.fledge.fledgeserver.member.entity.Member; +import org.springframework.security.core.Authentication; + +import java.security.Principal; + +import static com.fledge.fledgeserver.exception.ErrorCode.MEMBER_NOT_FOUND; + +import org.springframework.security.core.context.SecurityContextHolder; + +public class SecurityUtils { + + // TODO : 인증객체 가져오는 방식 통일한 뒤 사용하지 않는 메소드 정리 + + public static OAuthUserImpl getCurrentUser(Principal principal) { + if (principal == null) { + throw new CustomException(MEMBER_NOT_FOUND); + } + + if (principal instanceof Authentication) { + Authentication authentication = (Authentication) principal; + Object userPrincipal = authentication.getPrincipal(); + + if (userPrincipal instanceof OAuthUserImpl) { + return (OAuthUserImpl) userPrincipal; + } + } + + throw new CustomException(MEMBER_NOT_FOUND); + } + + public static OAuthUserImpl getCurrentUser() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication == null || !authentication.isAuthenticated()) { + throw new CustomException(MEMBER_NOT_FOUND); + } + + Object principal = authentication.getPrincipal(); + if (principal instanceof OAuthUserImpl) { + return (OAuthUserImpl) principal; + } else { + throw new CustomException(MEMBER_NOT_FOUND); + } + } + + public static Long getCurrentUserId(Principal principal) { + return Long.valueOf(getCurrentUser(principal).getUsername()); + } + + public static Long getCurrentUserId() { + return Long.valueOf(getCurrentUser().getUsername()); + } + + public static Member getCurrentMember(OAuthUserImpl oAuthUser) { + if (oAuthUser == null) { + throw new CustomException(MEMBER_NOT_FOUND); + } + return oAuthUser.getMember(); + } + + public static Member getCurrentMember() { + if (getCurrentUser() == null) { + throw new CustomException(MEMBER_NOT_FOUND); + } + return getCurrentUser().getMember(); + } + +} diff --git a/src/main/java/com/fledge/fledgeserver/common/utils/TimeUtils.java b/src/main/java/com/fledge/fledgeserver/common/utils/TimeUtils.java new file mode 100644 index 0000000..92af39b --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/common/utils/TimeUtils.java @@ -0,0 +1,20 @@ +package com.fledge.fledgeserver.common.utils; + +import lombok.RequiredArgsConstructor; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +@RequiredArgsConstructor +public class TimeUtils { + public static String refineToDateTime(LocalDateTime localDateTime) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return localDateTime.format(formatter); + } + + public static String refineToDate(LocalDate localDate) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일"); + return localDate.format(formatter); + } +} \ No newline at end of file diff --git a/src/main/java/com/fledge/fledgeserver/config/WebSecurityConfig.java b/src/main/java/com/fledge/fledgeserver/config/WebSecurityConfig.java index bb67cf1..5c01d0f 100644 --- a/src/main/java/com/fledge/fledgeserver/config/WebSecurityConfig.java +++ b/src/main/java/com/fledge/fledgeserver/config/WebSecurityConfig.java @@ -78,11 +78,10 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti return http.build(); } - @Bean + @Bean public WebSecurityCustomizer webSecurityCustomizer() { return web -> web.ignoring() .requestMatchers("/error", "/favicon.ico", "/swagger-ui/**", "/api-docs/**"); - } diff --git a/src/main/java/com/fledge/fledgeserver/exception/ErrorCode.java b/src/main/java/com/fledge/fledgeserver/exception/ErrorCode.java index 60ab61b..60e9800 100644 --- a/src/main/java/com/fledge/fledgeserver/exception/ErrorCode.java +++ b/src/main/java/com/fledge/fledgeserver/exception/ErrorCode.java @@ -29,7 +29,11 @@ public enum ErrorCode { // canary profile CANARY_NOT_FOUND(NOT_FOUND, "자립준비청년을 찾을 수 없습니다."), - DUPLICATE_APPLICATION(HttpStatus.CONFLICT, "이미 신청된 유저입니다."); + DUPLICATE_APPLICATION(HttpStatus.CONFLICT, "이미 신청된 유저입니다."), + + // support + UNAUTHORIZED_REQUEST(UNAUTHORIZED, "권한이 없습니다."), + SUPPORT_NOT_FOUND(NOT_FOUND, "후원 요청 게시글을 찾을 수 없습니다."); private final HttpStatus httpStatus; private final String message; diff --git a/src/main/java/com/fledge/fledgeserver/member/controller/MemberController.java b/src/main/java/com/fledge/fledgeserver/member/controller/MemberController.java index 08bd377..866d175 100644 --- a/src/main/java/com/fledge/fledgeserver/member/controller/MemberController.java +++ b/src/main/java/com/fledge/fledgeserver/member/controller/MemberController.java @@ -1,5 +1,6 @@ package com.fledge.fledgeserver.member.controller; +import com.fledge.fledgeserver.auth.dto.OAuthUserImpl; import com.fledge.fledgeserver.member.dto.MemberNicknameUpdateRequest; import com.fledge.fledgeserver.member.dto.MemberResponse; import com.fledge.fledgeserver.member.service.MemberService; @@ -7,18 +8,13 @@ import com.fledge.fledgeserver.response.SuccessStatus; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.beans.factory.annotation.Autowired; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; import io.swagger.v3.oas.annotations.Operation; -import static com.fledge.fledgeserver.response.SuccessStatus.CREATE_SUPPORT_SUCCESS; -import static com.fledge.fledgeserver.response.SuccessStatus.MEMBER_INFO_RETRIEVAL_SUCCESS; - @Tag(name = "회원 관리 API", description = "회원 관리와 관련된 API") @RestController @RequiredArgsConstructor @@ -31,8 +27,8 @@ public class MemberController { @Operation(summary = "현재 유저 정보 조회", description = "현재 인증된 유저의 정보를 조회합니다.") @GetMapping("/me") public ResponseEntity> memberInfo( - @AuthenticationPrincipal UserDetails userDetails) { - return ApiResponse.success(SuccessStatus.MEMBER_INFO_RETRIEVAL_SUCCESS, memberService.memberInfo(userDetails.getUsername())); + @AuthenticationPrincipal OAuthUserImpl oAuth2User) { + return ApiResponse.success(SuccessStatus.MEMBER_INFO_RETRIEVAL_SUCCESS, memberService.memberInfo(oAuth2User)); } @Operation(summary = "회원 상세 정보 조회", description = "회원 ID로 회원의 상세 정보를 조회합니다.") @@ -48,8 +44,8 @@ public ResponseEntity> getMemberDetails( public ResponseEntity> updateNickname( @Parameter(description = "회원 ID", required = true, example = "1") @PathVariable Long id, @Parameter(description = "닉네임 수정 요청", required = true) @RequestBody MemberNicknameUpdateRequest request, - @AuthenticationPrincipal UserDetails userDetails) { - MemberResponse memberResponse = memberService.updateNickname(id, request.getNickname(), userDetails.getUsername()); + @AuthenticationPrincipal OAuthUserImpl oAuth2User) { + MemberResponse memberResponse = memberService.updateNickname(id, request.getNickname(), oAuth2User); return ApiResponse.success(SuccessStatus.MEMBER_NICKNAME_UPDATE_SUCCESS, memberResponse); } } diff --git a/src/main/java/com/fledge/fledgeserver/member/repository/MemberRepository.java b/src/main/java/com/fledge/fledgeserver/member/repository/MemberRepository.java index ae790c8..01e56b2 100644 --- a/src/main/java/com/fledge/fledgeserver/member/repository/MemberRepository.java +++ b/src/main/java/com/fledge/fledgeserver/member/repository/MemberRepository.java @@ -8,5 +8,7 @@ public interface MemberRepository extends JpaRepository { Optional findBySocialId(Long socialId); Optional findByEmailAndActiveTrue(String email); + + Optional findMemberById(Long memberId); } diff --git a/src/main/java/com/fledge/fledgeserver/member/service/MemberService.java b/src/main/java/com/fledge/fledgeserver/member/service/MemberService.java index 2e4994a..58849ba 100644 --- a/src/main/java/com/fledge/fledgeserver/member/service/MemberService.java +++ b/src/main/java/com/fledge/fledgeserver/member/service/MemberService.java @@ -1,5 +1,7 @@ package com.fledge.fledgeserver.member.service; +import com.fledge.fledgeserver.auth.dto.OAuthUserImpl; +import com.fledge.fledgeserver.common.utils.SecurityUtils; import com.fledge.fledgeserver.exception.CustomException; import com.fledge.fledgeserver.member.dto.MemberResponse; import com.fledge.fledgeserver.member.entity.Member; @@ -18,9 +20,9 @@ public class MemberService { private final MemberRepository memberRepository; @Transactional(readOnly = true) - public MemberResponse memberInfo(String email) { - Member member = memberRepository.findByEmailAndActiveTrue(email) - .orElseThrow(() -> new CustomException(MEMBER_NOT_FOUND)); + public MemberResponse memberInfo(OAuthUserImpl oAuth2User) { + Member member = SecurityUtils.getCurrentMember(oAuth2User); + return new MemberResponse(member); } @@ -28,14 +30,13 @@ public MemberResponse memberInfo(String email) { public MemberResponse getMemberDetails(Long memberId) { Member member = memberRepository.findById(memberId) .orElseThrow(() -> new CustomException(MEMBER_NOT_FOUND)); + return new MemberResponse(member); } @Transactional - public MemberResponse updateNickname(Long memberId, String newNickname, String currentUserEmail) { - - Member member = memberRepository.findByEmailAndActiveTrue(currentUserEmail) - .orElseThrow(() -> new CustomException(MEMBER_NOT_FOUND)); + public MemberResponse updateNickname(Long memberId, String newNickname, OAuthUserImpl oAuth2User) { + Member member = SecurityUtils.getCurrentMember(oAuth2User); if (member.getId() != memberId){ throw new CustomException(MEMBER_FORBIDDEN); diff --git a/src/main/java/com/fledge/fledgeserver/promise/entity/Promise.java b/src/main/java/com/fledge/fledgeserver/promise/entity/Promise.java new file mode 100644 index 0000000..12812f3 --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/promise/entity/Promise.java @@ -0,0 +1,14 @@ +package com.fledge.fledgeserver.promise.entity; + + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum Promise { + ONCE("ONCE"), // 1회 인증 + WEEKLY("WEEKLY"), // 4주간 매 주 인증 + MONTHLY("MONTHLY"); // 3개월간 매 달 인증 + + private final String key; + public String getKey() { return key; } +} \ No newline at end of file diff --git a/src/main/java/com/fledge/fledgeserver/promise/entity/PromiseLog.java b/src/main/java/com/fledge/fledgeserver/promise/entity/PromiseLog.java new file mode 100644 index 0000000..cde2607 --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/promise/entity/PromiseLog.java @@ -0,0 +1,48 @@ +package com.fledge.fledgeserver.promise.entity; + +import com.fledge.fledgeserver.common.entity.BaseTimeEntity; +import com.fledge.fledgeserver.member.entity.Member; +import com.fledge.fledgeserver.support.entity.Support; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class PromiseLog extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "support_id", nullable = false) + private Support support; + + @Column(nullable = false) + private LocalDate startDate; + + @Column(nullable = false) + private LocalDate endDate; + + @Column(nullable = false) + private PromiseStatus promiseStatus; + + @Builder + public PromiseLog(Member member, Support support, LocalDate startDate, LocalDate endDate, PromiseStatus promiseStatus) { + this.member = member; + this.support = support; + this.startDate = startDate; + this.endDate = endDate; + this.promiseStatus = promiseStatus; + } +} diff --git a/src/main/java/com/fledge/fledgeserver/promise/entity/PromiseStatus.java b/src/main/java/com/fledge/fledgeserver/promise/entity/PromiseStatus.java new file mode 100644 index 0000000..c795d1b --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/promise/entity/PromiseStatus.java @@ -0,0 +1,17 @@ +package com.fledge.fledgeserver.promise.entity; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum PromiseStatus { + PENDING("PENDING"), // 인증 대기중 + VERIFIED("VERIFIED"), // 인증 완료 + UNVERIFIED("UNVERIFIED"); // 인증하지 않음 + + + private final String key; + + public String getStatus() { + return key; + } +} diff --git a/src/main/java/com/fledge/fledgeserver/response/SuccessStatus.java b/src/main/java/com/fledge/fledgeserver/response/SuccessStatus.java index 833caf6..8ab9629 100644 --- a/src/main/java/com/fledge/fledgeserver/response/SuccessStatus.java +++ b/src/main/java/com/fledge/fledgeserver/response/SuccessStatus.java @@ -20,13 +20,17 @@ public enum SuccessStatus { * support */ CREATE_SUPPORT_SUCCESS(HttpStatus.CREATED, "후원하기 게시글 등록 성공"), + GET_SUPPORT_SUCCESS(HttpStatus.OK, "후원하기 상세 페이지 조회 성공"), + GET_SUPPORT_FOR_UPDATE_SUCCESS(HttpStatus.OK, "수정을 위한 후원하기 조회 성공"), + UPDATE_SUPPORT_SUCCESS(HttpStatus.OK, "후원하기 게시글 업데이트 성공"), /** * canary */ PROFILE_APPLICATION_SUCCESS(HttpStatus.OK, "프로필 신청 성공"), PROFILE_RETRIEVAL_SUCCESS(HttpStatus.OK, "프로필 조회 성공"), - PROFILE_UPDATE_SUCCESS(HttpStatus.NO_CONTENT, "프로필 수정 성공"); + PROFILE_UPDATE_SUCCESS(HttpStatus.NO_CONTENT, "프로필 수정 성공"), + DELIVERY_INFO_GET_SUCCESS(HttpStatus.OK, "배송지 조회 성공"); private final HttpStatus httpStatus; diff --git a/src/main/java/com/fledge/fledgeserver/support/controller/SupportController.java b/src/main/java/com/fledge/fledgeserver/support/controller/SupportController.java index c815832..77ee4ef 100644 --- a/src/main/java/com/fledge/fledgeserver/support/controller/SupportController.java +++ b/src/main/java/com/fledge/fledgeserver/support/controller/SupportController.java @@ -1,18 +1,23 @@ package com.fledge.fledgeserver.support.controller; +import com.fledge.fledgeserver.common.utils.SecurityUtils; import com.fledge.fledgeserver.response.ApiResponse; +import com.fledge.fledgeserver.response.SuccessStatus; import com.fledge.fledgeserver.support.dto.request.SupportCreateRequestDto; +import com.fledge.fledgeserver.support.dto.request.SupportUpdateRequestDto; +import com.fledge.fledgeserver.support.dto.response.SupportGetForUpdateResponseDto; +import com.fledge.fledgeserver.support.dto.response.SupportGetResponseDto; import com.fledge.fledgeserver.support.service.SupportService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.security.Principal; import static com.fledge.fledgeserver.response.SuccessStatus.CREATE_SUPPORT_SUCCESS; +import static com.fledge.fledgeserver.response.SuccessStatus.GET_SUPPORT_SUCCESS; @Tag(name = "후원하기 API", description = "후원하기와 관련된 API") @RestController @@ -20,13 +25,82 @@ @RequiredArgsConstructor public class SupportController { private final SupportService supportService; + /** + * ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ후원 게시글 관련ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ + */ + /** + * CREATE + */ @Operation(summary = "후원하기 게시글 등록", description = "후원하기 게시글을 등록합니다.(자립 준비 청소년만)") @PostMapping - public ResponseEntity> createSupport(@RequestBody SupportCreateRequestDto supportCreateRequestDto){ - supportService.createSupport(supportCreateRequestDto); + public ResponseEntity> createSupport( + Principal principal, + @RequestBody SupportCreateRequestDto supportCreateRequestDto + ) { + Long memberId = SecurityUtils.getCurrentUserId(principal); + supportService.createSupport(memberId, supportCreateRequestDto); return ApiResponse.success(CREATE_SUPPORT_SUCCESS); } + /** + * READ + */ +// +// @Operation(summary = "후원하기 게시글 조회", description = "후원하기 게시글을 조회합니다.(모든 회원 가능)") +// @GetMapping("/{supportId}") +// public ResponseEntity> getSupport( +// @PathVariable(value = "supportId") Long supportId +// ) { +// // TODO :: 후원하기(후원자) & 후원 인증 관련 로직 추가 +// return ApiResponse.success(GET_SUPPORT_SUCCESS, supportService.getSupport(supportId)); +// } +// +// /** +// * UPDATE +// */ +// +// @Operation(summary = "후원하기 게시글 수정 시 기존 데이터 조회", description = "후원하기 게시글의 기존 데이터를 반환합니다.") +// @GetMapping("/{supportId}/update") +// public ResponseEntity> getSupportForUpdate( +// @PathVariable(value = "supportId") Long supportId, +// Principal principal +// ) { +// Long memberId = SecurityUtils.getCurrentUserId(principal); +// return ApiResponse.success( +// SuccessStatus.GET_SUPPORT_FOR_UPDATE_SUCCESS, +// supportService.getSupportForUpdate(memberId, supportId) +// ); +// } +// +// @Operation(summary = "후원하기 게시글 수정", description = "후원하기 게시글을 수정합니다.") +// @PutMapping("/{supportId}") +// public ResponseEntity> updateSupport( +// Principal principal, +// @PathVariable(value = "supportId") Long supportId, +// @RequestBody SupportUpdateRequestDto supportUpdateRequestDto +// ) { +// Long memberId = SecurityUtils.getCurrentUserId(principal); +// supportService.updateSupport(memberId, supportId, supportUpdateRequestDto); +// return ApiResponse.success(SuccessStatus.UPDATE_SUPPORT_SUCCESS); +// } + + /** + * DELETE + */ + // TODO :: 후원하기 게시글 삭제 API + + + /** + * ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ후원 하기ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ + */ + /** + * 후원하기 팝업에서 정보 조회 + */ + + + /** + * 후원하기 시 후원 처리 + */ } diff --git a/src/main/java/com/fledge/fledgeserver/support/dto/request/SupportCreateRequestDto.java b/src/main/java/com/fledge/fledgeserver/support/dto/request/SupportCreateRequestDto.java index ab958e4..48905fe 100644 --- a/src/main/java/com/fledge/fledgeserver/support/dto/request/SupportCreateRequestDto.java +++ b/src/main/java/com/fledge/fledgeserver/support/dto/request/SupportCreateRequestDto.java @@ -6,7 +6,7 @@ import lombok.Setter; import org.hibernate.validator.constraints.URL; -import java.time.LocalDateTime; +import java.time.LocalDate; import java.util.List; @Getter @@ -24,6 +24,12 @@ public class SupportCreateRequestDto { @Size(max = 500, message = "후원 사유는 최대 500자까지 입력 가능합니다.") private String reason; + @Schema(description = "후원자의 약속", required = true, example = "ONCE") + @NotBlank(message = "후원자의 약속은 필수입니다.") + @Pattern(regexp = "ONCE|WEEKLY|MONTHLY", + message = "후원자의 약속은 ONCE, WEEKLY, MONTHLY 중 하나여야 합니다.") + private String promise; + @Schema(description = "후원 물품 명", required = true, example = "노트북") @NotBlank(message = "후원 물품 명은 필수입니다.") @Size(max = 100, message = "후원 물품 명은 최대 100자까지 입력 가능합니다.") @@ -42,18 +48,37 @@ public class SupportCreateRequestDto { @Schema(description = "후원 물품 이미지 리스트", required = true) private List images; - @Schema(description = "후원 인증 기간", required = true, example = "30") - @NotBlank(message = "후원 인증 기간은 필수입니다.") - @Positive(message = "후원 인증 기간은 0보다 큰 값이어야 합니다.") - private int checkPeriod; - - @Schema(description = "후원 인증 횟수", required = true, example = "1") - @NotBlank(message = "후원 인증 횟수는 필수입니다.") - @Positive(message = "후원 인증 횟수는 0보다 큰 값이어야 합니다.") - private int checkCount; - - @Schema(description = "만료 시점", required = true, example = "2024-12-31T23:59:59") + @Schema(description = "만료 시점", required = true, example = "2024-12-31") @NotBlank(message = "만료 시점은 필수입니다.") @Future(message = "만료 시점은 현재 시간 이후여야 합니다.") - private LocalDateTime expirationTime; + private LocalDate expirationDate; + + @Schema(description = "후원 카테고리", example = "FOOD") + @NotBlank(message = "후원 카테고리는 필수입니다.") + @Pattern(regexp = "DAILY_NECESSITY|FOOD|HOME_APPLIANCES|EDUCATION|MEDICAL|LEGAL_AID|ETC", + message = "후원 카테고리는 DAILY_NECESSITY, FOOD, HOME_APPLIANCES, EDUCATION, MEDICAL, LEGAL_AID, ETC 중 하나여야 합니다.") + private String supportCategory; + + // MEDICAL, LEGAL_AID인 겨우 + @Schema(description = "은행명", example = "카카오뱅크") + private String bank; + + @Schema(description = "은행 계좌번호", example = "1234-12-1234-12") + private String account; + + // DAILY_NECESSITY, FOOD, HOME_APPLIANCES, EDUCATION, ETC인 경우 + @Schema(description = "수령인 이름", example = "홍길동") + private String recipientName; + + @Schema(description = "전화번호", example = "010-1234-5678") + private String phone; + + @Schema(description = "주소", example = "서울특별시 노원구 공릉로232") + private String address; + + @Schema(description = "상세 주소", example = "OO빌라 101호") + private String detailAddress; + + @Schema(description = "우편번호", example = "123456") + private String zip; } diff --git a/src/main/java/com/fledge/fledgeserver/support/dto/request/SupportUpdateRequestDto.java b/src/main/java/com/fledge/fledgeserver/support/dto/request/SupportUpdateRequestDto.java new file mode 100644 index 0000000..ed858c7 --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/support/dto/request/SupportUpdateRequestDto.java @@ -0,0 +1,82 @@ +package com.fledge.fledgeserver.support.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Future; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.URL; + +import java.time.LocalDate; +import java.util.List; + +@Getter +@Setter +@Schema(description = "후원하기 게시글 수정 DTO") +public class SupportUpdateRequestDto { + + @Schema(description = "후원 게시글 제목", required = true, example = "후원 요청") + @NotBlank(message = "제목은 필수입니다.") + @Size(max = 100, message = "제목은 최대 100자까지 입력 가능합니다.") + private String title; + + @Schema(description = "후원 필요한 이유", required = true, example = "자립을 위한 후원") + @NotBlank(message = "후원 사유는 필수입니다.") + @Size(max = 500, message = "후원 사유는 최대 500자까지 입력 가능합니다.") + private String reason; + + @Schema(description = "후원 물품 명", required = true, example = "노트북") + @NotBlank(message = "후원 물품 명은 필수입니다.") + @Size(max = 100, message = "후원 물품 명은 최대 100자까지 입력 가능합니다.") + private String item; + + @Schema(description = "구매 URL", required = true, example = "https://example.com/product/1") + @NotBlank(message = "구매 URL은 필수입니다.") + @URL(message = "유효한 URL 형식이어야 합니다.") + private String purchaseUrl; + + @Schema(description = "후원 물품 가격", required = true, example = "500000") + @NotBlank(message = "후원 물품 가격은 필수입니다.") + @Positive(message = "가격은 0보다 큰 값이어야 합니다.") + private int price; + + @Schema(description = "후원 물품 이미지 리스트", required = true) + private List images; + + @Schema(description = "후원 인증 기간", required = true, example = "30") + @NotBlank(message = "후원 인증 기간은 필수입니다.") + @Positive(message = "후원 인증 기간은 0보다 큰 값이어야 합니다.") + private int checkPeriod; + + @Schema(description = "후원 인증 횟수", required = true, example = "1") + @NotBlank(message = "후원 인증 횟수는 필수입니다.") + @Positive(message = "후원 인증 횟수는 0보다 큰 값이어야 합니다.") + private int checkCount; + + @Schema(description = "만료 시점", required = true, example = "2024-12-31") + @NotBlank(message = "만료 시점은 필수입니다.") + @Future(message = "만료 시점은 현재 시간 이후여야 합니다.") + private LocalDate expirationDate; + + @Schema(description = "수령인 이름", required = true, example = "홍길동") + @NotBlank(message = "수령인 이름은 필수입니다.") + private String recipientName; + + @Schema(description = "전화번호", required = true, example = "010-1234-5678") + @NotBlank(message = "전화번호는 필수입니다.") + private String phone; + + @Schema(description = "주소", required = true, example = "서울특별시 노원구 공릉로232") + @NotBlank(message = "주소는 필수입니다.") + private String address; + + @Schema(description = "상세 주소", required = true, example = "OO빌라 101호") + @NotBlank(message = "상세 주소는 필수입니다.") + private String detailAddress; + + @Schema(description = "우편번호", required = true, example = "123456") + @NotBlank(message = "우편번호는 필수입니다.") + private String zip; +} diff --git a/src/main/java/com/fledge/fledgeserver/support/dto/response/SupportGetForUpdateResponseDto.java b/src/main/java/com/fledge/fledgeserver/support/dto/response/SupportGetForUpdateResponseDto.java new file mode 100644 index 0000000..074d3db --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/support/dto/response/SupportGetForUpdateResponseDto.java @@ -0,0 +1,59 @@ +package com.fledge.fledgeserver.support.dto.response; + +import com.fledge.fledgeserver.common.utils.TimeUtils; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +import java.time.LocalDate; +import java.util.List; + +@Getter +@Schema(description = "후원하기 게시글 수정 시 기존 데이터 조회 DTO") +public class SupportGetForUpdateResponseDto { + @Schema(description = "멤버 식별자(프로필 팝업 띄우기)", example = "2") + private Long memberId; + + @Schema(description = "작성자 닉네임", example = "카드값줘체리") + private String nickname; + + @Schema(description = "후원 게시글 제목", example = "후원 요청") + private String title; + + @Schema(description = "후원 필요한 이유", example = "자립을 위한 후원") + private String reason; + + @Schema(description = "후원 물품 명", example = "노트북") + private String item; + + @Schema(description = "구매 URL", example = "https://example.com/product/1") + private String purchaseUrl; + + @Schema(description = "후원 물품 가격", example = "500000") + private int price; + + @Schema(description = "후원 물품 이미지 리스트") + private List images; + + @Schema(description = "후원 인증 기간", example = "30") + private int checkPeriod; + + @Schema(description = "후원 인증 횟수", example = "1") + private int checkCount; + + @Schema(description = "후원 만료 시점", example = "2024-07-31") + private String expirationDate; + + public SupportGetForUpdateResponseDto(Long memberId, String nickname, String title, String reason, String item, String purchaseUrl, int price, List images, int checkPeriod, int checkCount, LocalDate expirationDate) { + this.memberId = memberId; + this.nickname = nickname; + this.title = title; + this.reason = reason; + this.item = item; + this.purchaseUrl = purchaseUrl; + this.price = price; + this.images = images; + this.checkPeriod = checkPeriod; + this.checkCount = checkCount; + this.expirationDate = TimeUtils.refineToDate(expirationDate); + } +} diff --git a/src/main/java/com/fledge/fledgeserver/support/dto/response/SupportGetResponseDto.java b/src/main/java/com/fledge/fledgeserver/support/dto/response/SupportGetResponseDto.java new file mode 100644 index 0000000..e96173f --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/support/dto/response/SupportGetResponseDto.java @@ -0,0 +1,61 @@ +package com.fledge.fledgeserver.support.dto.response; + +import com.fledge.fledgeserver.common.utils.TimeUtils; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +import java.time.LocalDate; +import java.util.List; + +@Getter +@Schema(description = "후원하기 게시글 조회 DTO") +public class SupportGetResponseDto { + + @Schema(description = "멤버 식별자(프로필 팝업 띄우기)", example = "2") + private Long memberId; + +// @Schema(description = "", example = "") +@Schema(description = "작성자 닉네임", example = "카드값줘체리") + private String nickname; + + @Schema(description = "후원 게시글 제목", example = "후원 요청") + private String title; + + @Schema(description = "후원 필요한 이유", example = "자립을 위한 후원") + private String reason; + + @Schema(description = "후원 물품 명", example = "노트북") + private String item; + + @Schema(description = "구매 URL", example = "https://example.com/product/1") + private String purchaseUrl; + + @Schema(description = "후원 물품 가격", example = "500000") + private int price; + + @Schema(description = "후원 물품 이미지 리스트") + private List images; + + @Schema(description = "후원 인증 기간", example = "30") + private int checkPeriod; + + @Schema(description = "후원 인증 횟수", example = "1") + private int checkCount; + + @Schema(description = "후원 만료 시점", example = "2024-07-31") + private String expirationDate; + + public SupportGetResponseDto(Long memberId, String nickname, String title, String reason, String item, String purchaseUrl, int price, List images, int checkPeriod, int checkCount, LocalDate expirationDate) { + this.memberId = memberId; + this.nickname = nickname; + this.title = title; + this.reason = reason; + this.item = item; + this.purchaseUrl = purchaseUrl; + this.price = price; + this.images = images; + this.checkPeriod = checkPeriod; + this.checkCount = checkCount; + this.expirationDate = TimeUtils.refineToDate(expirationDate); + } +} diff --git a/src/main/java/com/fledge/fledgeserver/support/entity/Support.java b/src/main/java/com/fledge/fledgeserver/support/entity/Support.java index 83e14a1..de2a7ba 100644 --- a/src/main/java/com/fledge/fledgeserver/support/entity/Support.java +++ b/src/main/java/com/fledge/fledgeserver/support/entity/Support.java @@ -1,13 +1,17 @@ package com.fledge.fledgeserver.support.entity; import com.fledge.fledgeserver.common.entity.BaseTimeEntity; +import com.fledge.fledgeserver.member.entity.Member; +import com.fledge.fledgeserver.promise.entity.Promise; +import com.fledge.fledgeserver.support.dto.request.SupportCreateRequestDto; +import com.fledge.fledgeserver.support.dto.request.SupportUpdateRequestDto; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @@ -20,6 +24,10 @@ public class Support extends BaseTimeEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") //댓글 작성자 id + private Member member; + @Column(nullable = false) private String title; @@ -39,26 +47,90 @@ public class Support extends BaseTimeEntity { private List images = new ArrayList<>(); @Column(nullable = false) - private int checkPeriod; + private LocalDate expirationDate; + + @Column(nullable = false) + private Boolean expirationStatus = false; @Column(nullable = false) - private int checkCount; + @Enumerated(value = EnumType.STRING) + private Promise promise; // 인증 주기 및 횟수 @Column(nullable = false) - private LocalDateTime expirationTime; + @Enumerated(value = EnumType.STRING) + private SupportCategory supportCategory; + + // ------의료비 또는 법률구조비------ + @Column(nullable = true) + private String bank; + + @Column(nullable = true) + private String account; + + // -----------기타----------- + @Column(nullable = true) + private String recipientName; + + @Column(nullable = true) + private String phone; + + @Column(nullable = true) + private String address; + + @Column(nullable = true) + private String detailAddress; + + @Column(nullable = true) + private String zip; // TODO :: 챌린지 구현 후 참여 중이거나 완료한 챌린지(뱃지)에 대한 로직 추가 @Builder - public Support(String title, String reason, String item, String purchaseUrl, int price, int checkPeriod, int checkCount, LocalDateTime expirationTime) { - this.title = title; - this.reason = reason; - this.item = item; - this.purchaseUrl = purchaseUrl; - this.price = price; - this.checkPeriod = checkPeriod; - this.checkCount = checkCount; - this.expirationTime = expirationTime; + public Support(Member member, SupportCreateRequestDto supportCreateRequestDto) { + this.member = member; + this.title = supportCreateRequestDto.getTitle(); + this.reason = supportCreateRequestDto.getReason(); + this.item = supportCreateRequestDto.getItem(); + this.purchaseUrl = supportCreateRequestDto.getPurchaseUrl(); + this.price = supportCreateRequestDto.getPrice(); + this.expirationDate = supportCreateRequestDto.getExpirationDate(); + this.promise = Promise.valueOf(supportCreateRequestDto.getPromise()); + this.supportCategory = SupportCategory.valueOf(supportCreateRequestDto.getSupportCategory()); + + if ("MEDICAL".equals(supportCategory.name()) || "LEGAL_AID".equals(supportCategory.name())) { + this.bank = supportCreateRequestDto.getBank(); + this.account = supportCreateRequestDto.getAccount(); + this.recipientName = null; + this.phone = null; + this.address = null; + this.detailAddress = null; + this.zip = null; + } else { + this.recipientName = supportCreateRequestDto.getRecipientName(); + this.phone = supportCreateRequestDto.getPhone(); + this.address = supportCreateRequestDto.getAddress(); + this.detailAddress = supportCreateRequestDto.getDetailAddress(); + this.zip = supportCreateRequestDto.getZip(); + this.bank = null; + this.account = null; + } } + + + + public void update(SupportUpdateRequestDto supportUpdateRequestDto) { + this.title = supportUpdateRequestDto.getTitle(); + this.reason = supportUpdateRequestDto.getReason(); + this.item = supportUpdateRequestDto.getItem(); + this.purchaseUrl = supportUpdateRequestDto.getPurchaseUrl(); + this.price = supportUpdateRequestDto.getPrice(); + this.recipientName = supportUpdateRequestDto.getRecipientName(); + this.phone = supportUpdateRequestDto.getPhone(); + this.address = supportUpdateRequestDto.getAddress(); + this.detailAddress = supportUpdateRequestDto.getDetailAddress(); + this.zip = supportUpdateRequestDto.getZip(); + this.expirationDate = supportUpdateRequestDto.getExpirationDate(); + } + } diff --git a/src/main/java/com/fledge/fledgeserver/support/entity/SupportCategory.java b/src/main/java/com/fledge/fledgeserver/support/entity/SupportCategory.java new file mode 100644 index 0000000..70cc2bc --- /dev/null +++ b/src/main/java/com/fledge/fledgeserver/support/entity/SupportCategory.java @@ -0,0 +1,19 @@ +package com.fledge.fledgeserver.support.entity; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum SupportCategory { + DAILY_NECESSITY("DAILY_NECESSITY"), // 생필품 + FOOD("FOOD"), // 식품 + HOME_APPLIANCES("HOME_APPLIANCES"), // 가전제품 + EDUCATION("EDUCATION"), // 교육비/교재비 + MEDICAL("MEDICAL"), // 의료비 + LEGAL_AID("LEGAL_AID"), // 법률 구조비 + ETC("ETC"); // 기타 + + private final String key; + public String getKey() { + return key; + } +} \ No newline at end of file diff --git a/src/main/java/com/fledge/fledgeserver/support/entity/SupportRecord.java b/src/main/java/com/fledge/fledgeserver/support/entity/SupportRecord.java index caf9662..8c0a220 100644 --- a/src/main/java/com/fledge/fledgeserver/support/entity/SupportRecord.java +++ b/src/main/java/com/fledge/fledgeserver/support/entity/SupportRecord.java @@ -1,18 +1,36 @@ package com.fledge.fledgeserver.support.entity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.fledge.fledgeserver.common.entity.BaseTimeEntity; +import com.fledge.fledgeserver.member.entity.Member; +import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class SupportRecord { +public class SupportRecord extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @ManyToOne(fetch = FetchType.LAZY) // Member와의 다대일 관계 + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) // Support와의 다대일 관계 + @JoinColumn(name = "support_id", nullable = false) + private Support support; + + @Column(nullable = false) + private String account; + + @Builder + public SupportRecord(Member member, Support support, String account) { + this.member = member; + this.support = support; + this.account = account; + } } diff --git a/src/main/java/com/fledge/fledgeserver/support/repository/SupportRepository.java b/src/main/java/com/fledge/fledgeserver/support/repository/SupportRepository.java index fd006ba..6ce104e 100644 --- a/src/main/java/com/fledge/fledgeserver/support/repository/SupportRepository.java +++ b/src/main/java/com/fledge/fledgeserver/support/repository/SupportRepository.java @@ -2,6 +2,18 @@ import com.fledge.fledgeserver.support.entity.Support; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.Optional; public interface SupportRepository extends JpaRepository { + /** + * 한방 쿼리: Fetch Join + */ + @Query("SELECT s FROM Support s " + + "JOIN FETCH s.member m " + + "LEFT JOIN FETCH s.images i " + + "WHERE s.id = :supportId") + Optional findSupportByIdWithFetch(@Param("supportId") Long supportId); } diff --git a/src/main/java/com/fledge/fledgeserver/support/service/SupportService.java b/src/main/java/com/fledge/fledgeserver/support/service/SupportService.java index f366415..fdc1c2d 100644 --- a/src/main/java/com/fledge/fledgeserver/support/service/SupportService.java +++ b/src/main/java/com/fledge/fledgeserver/support/service/SupportService.java @@ -1,6 +1,16 @@ package com.fledge.fledgeserver.support.service; +import com.fledge.fledgeserver.canary.repository.CanaryProfileRepository; +import com.fledge.fledgeserver.exception.CustomException; +import com.fledge.fledgeserver.exception.ErrorCode; +import com.fledge.fledgeserver.file.FileService; +import com.fledge.fledgeserver.member.entity.Member; +import com.fledge.fledgeserver.member.entity.Role; +import com.fledge.fledgeserver.member.repository.MemberRepository; import com.fledge.fledgeserver.support.dto.request.SupportCreateRequestDto; +import com.fledge.fledgeserver.support.dto.request.SupportUpdateRequestDto; +import com.fledge.fledgeserver.support.dto.response.SupportGetForUpdateResponseDto; +import com.fledge.fledgeserver.support.dto.response.SupportGetResponseDto; import com.fledge.fledgeserver.support.entity.Support; import com.fledge.fledgeserver.support.entity.SupportImage; import com.fledge.fledgeserver.support.repository.SupportImageRepository; @@ -9,25 +19,31 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Service @Transactional @RequiredArgsConstructor public class SupportService { + private final MemberRepository memberRepository; + private final CanaryProfileRepository canaryProfileRepository; private final SupportRepository supportRepository; + private final FileService fileService; private final SupportImageRepository supportImageRepository; - public void createSupport(SupportCreateRequestDto supportCreateRequestDto) { + public void createSupport(Long memberId, SupportCreateRequestDto supportCreateRequestDto) { + Member member = memberRepository.findMemberById(memberId) + .orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND)); + + if (member.getRole() != Role.CANARY) { + throw new CustomException(ErrorCode.UNAUTHORIZED_REQUEST); + } Support support = Support.builder() - .title(supportCreateRequestDto.getTitle()) - .reason(supportCreateRequestDto.getReason()) - .item((supportCreateRequestDto.getItem())) - .price(supportCreateRequestDto.getPrice()) - .purchaseUrl(supportCreateRequestDto.getPurchaseUrl()) - .checkPeriod(supportCreateRequestDto.getCheckPeriod()) - .checkCount(supportCreateRequestDto.getCheckCount()) - .expirationTime(supportCreateRequestDto.getExpirationTime()) + .member(member) + .supportCreateRequestDto(supportCreateRequestDto) .build(); + supportRepository.save(support); for (String imageUrl : supportCreateRequestDto.getImages()) { SupportImage supportImage = SupportImage.builder() @@ -37,4 +53,75 @@ public void createSupport(SupportCreateRequestDto supportCreateRequestDto) { support.getImages().add(supportImage); } } + +// public SupportGetResponseDto getSupport(Long supportId) { +// Support support = supportRepository.findSupportByIdWithFetch(supportId) +// .orElseThrow(() -> new CustomException(ErrorCode.SUPPORT_NOT_FOUND)); +// +// return new SupportGetResponseDto( +// support.getMember().getId(), +// support.getMember().getNickname(), +// support.getTitle(), +// support.getReason(), +// support.getItem(), +// support.getPurchaseUrl(), +// support.getPrice(), +// // Images Presigned-URL처리 +// support.getImages().stream() +// .map(supportImage -> fileService.getFileUrl(supportImage.getImageUrl())) +// .toList(), +// support.getExpirationDate() +// ); +// } +// +// public SupportGetForUpdateResponseDto getSupportForUpdate(Long memberId, Long supportId) { +// Support support = supportRepository.findSupportByIdWithFetch(supportId) +// .orElseThrow(() -> new CustomException(ErrorCode.SUPPORT_NOT_FOUND)); +// +// if (support.getMember().getId() != memberId) { +// throw new CustomException(ErrorCode.NO_ACCESS); +// } +// +// // 이미지를 Presigned URL로 처리 +// List imageUrls = support.getImages().stream() +// .map(supportImage -> fileService.getFileUrl(supportImage.getImageUrl())) +// .toList(); +// +// return new SupportGetForUpdateResponseDto( +// support.getMember().getId(), +// support.getMember().getNickname(), +// support.getTitle(), +// support.getReason(), +// support.getItem(), +// support.getPurchaseUrl(), +// support.getPrice(), +// imageUrls, +// support.getCheckPeriod(), +// support.getCheckCount(), +// support.getExpirationDate() +// ); +// } +// +// public void updateSupport(Long memberId, Long supportId, SupportUpdateRequestDto supportUpdateRequestDto) { +// Support support = supportRepository.findSupportByIdWithFetch(supportId) +// .orElseThrow(() -> new CustomException(ErrorCode.SUPPORT_NOT_FOUND)); +// +// if (support.getMember().getId() != memberId) { +// throw new CustomException(ErrorCode.NO_ACCESS); +// } +// support.update(supportUpdateRequestDto); +// support.getImages().clear(); +// +// List newImages = supportUpdateRequestDto.getImages().stream() +// .map(imageUrl -> new SupportImage(support, imageUrl)) +// .toList(); +// +// support.getImages().addAll(newImages); +// +// // 5. 기존 이미지 삭제 +// support.getImages().clear(); // 기존 이미지 제거 +// +// // 6. 새로운 이미지 추가 +// support.getImages().addAll(newImages); +// } }