From 0ff1871282d7826da56bddf582b9c31a52b80518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Sun, 10 Nov 2024 01:45:03 +0900 Subject: [PATCH 01/26] =?UTF-8?q?=EC=9E=84=EC=8B=9C=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/config/SecurityBeanGenerator.java | 9 +----- .../domain/auth/config/SecurityConfig.java | 3 -- .../member/controller/MemberController.java | 29 +++++++++++++++++++ .../dto/request/CustomerUpdateRequest.java | 7 +++++ .../dto/request/FarmerUpdateRequest.java | 11 +++++++ .../poomasi/domain/member/entity/Member.java | 2 +- .../domain/member/service/MemberService.java | 23 +++++++++++++++ 7 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 src/main/java/poomasi/domain/member/dto/request/CustomerUpdateRequest.java create mode 100644 src/main/java/poomasi/domain/member/dto/request/FarmerUpdateRequest.java diff --git a/src/main/java/poomasi/domain/auth/config/SecurityBeanGenerator.java b/src/main/java/poomasi/domain/auth/config/SecurityBeanGenerator.java index 2aa3d5d6..de30f9d0 100644 --- a/src/main/java/poomasi/domain/auth/config/SecurityBeanGenerator.java +++ b/src/main/java/poomasi/domain/auth/config/SecurityBeanGenerator.java @@ -2,20 +2,13 @@ import jdk.jfr.Description; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; import org.springframework.web.servlet.handler.HandlerMappingIntrospector; -import poomasi.domain.auth.token.blacklist.service.TokenBlacklistService; -import poomasi.domain.auth.token.refreshtoken.service.TokenStorageService; -import poomasi.domain.auth.token.util.JwtUtil; -import poomasi.domain.auth.token.refreshtoken.service.TokenRedisService; -import poomasi.domain.member.service.MemberService; + @RequiredArgsConstructor @Configuration diff --git a/src/main/java/poomasi/domain/auth/config/SecurityConfig.java b/src/main/java/poomasi/domain/auth/config/SecurityConfig.java index f6d7f746..cb1a269b 100644 --- a/src/main/java/poomasi/domain/auth/config/SecurityConfig.java +++ b/src/main/java/poomasi/domain/auth/config/SecurityConfig.java @@ -15,14 +15,11 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.security.web.authentication.logout.LogoutFilter; -import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; import poomasi.domain.auth.security.filter.CustomUsernamePasswordAuthenticationFilter; import poomasi.domain.auth.security.filter.JwtAuthenticationFilter; import poomasi.domain.auth.security.handler.CustomSuccessHandler; import poomasi.domain.auth.security.userdetail.OAuth2UserDetailServiceImpl; -import poomasi.domain.auth.security.handler.*; import poomasi.domain.auth.security.userdetail.UserDetailsServiceImpl; import poomasi.domain.auth.token.util.JwtUtil; diff --git a/src/main/java/poomasi/domain/member/controller/MemberController.java b/src/main/java/poomasi/domain/member/controller/MemberController.java index 2ee754f3..ad38dce9 100644 --- a/src/main/java/poomasi/domain/member/controller/MemberController.java +++ b/src/main/java/poomasi/domain/member/controller/MemberController.java @@ -9,7 +9,9 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; import poomasi.domain.auth.security.userdetail.UserDetailsImpl; +import poomasi.domain.member.dto.request.CustomerUpdateRequest; import poomasi.domain.member.dto.request.FarmerQualificationRequest; +import poomasi.domain.member.dto.request.FarmerUpdateRequest; import poomasi.domain.member.dto.response.MemberResponse; import poomasi.domain.member.dto.response.MemberSummaryResponse; import poomasi.domain.member.entity.Member; @@ -75,5 +77,32 @@ public ResponseEntity getMemberSummaryById(@PathVariable return ResponseEntity.ok(memberSummaryResponse); } + @PutMapping("/customer/update") + @Secured("ROLE_CUSTOMER") + public ResponseEntity updateCustomer( + @AuthenticationPrincipal UserDetailsImpl userDetails, + @RequestBody CustomerUpdateRequest customerUpdateRequest) { + + Member member = userDetails.getMember(); + Member updatedMember = memberService.updateCustomer(member, customerUpdateRequest); + + MemberResponse memberResponse = MemberResponse.fromEntity(updatedMember); + return ResponseEntity.ok(memberResponse); + } + + @PutMapping("/farmer/update") + @Secured("ROLE_FARMER") + public ResponseEntity updateFarmer( + @AuthenticationPrincipal UserDetailsImpl userDetails, + @RequestBody FarmerUpdateRequest farmerUpdateRequest) { + + Member member = userDetails.getMember(); + Member updatedMember = memberService.updateFarmer(member, farmerUpdateRequest); + + MemberResponse memberResponse = MemberResponse.fromEntity(updatedMember); + return ResponseEntity.ok(memberResponse); + } + + } diff --git a/src/main/java/poomasi/domain/member/dto/request/CustomerUpdateRequest.java b/src/main/java/poomasi/domain/member/dto/request/CustomerUpdateRequest.java new file mode 100644 index 00000000..e701460c --- /dev/null +++ b/src/main/java/poomasi/domain/member/dto/request/CustomerUpdateRequest.java @@ -0,0 +1,7 @@ +package poomasi.domain.member.dto.request; + +public record CustomerUpdateRequest( + String name, + String email, + String password) { +} diff --git a/src/main/java/poomasi/domain/member/dto/request/FarmerUpdateRequest.java b/src/main/java/poomasi/domain/member/dto/request/FarmerUpdateRequest.java new file mode 100644 index 00000000..3cac6814 --- /dev/null +++ b/src/main/java/poomasi/domain/member/dto/request/FarmerUpdateRequest.java @@ -0,0 +1,11 @@ +package poomasi.domain.member.dto.request; + +public record FarmerUpdateRequest( + String name, + String email, + String password, + String phoneNumber, + String storeName, + String storeAddress, + String storeAddressDetail) { +} diff --git a/src/main/java/poomasi/domain/member/entity/Member.java b/src/main/java/poomasi/domain/member/entity/Member.java index a18c99c2..67bc9ee8 100644 --- a/src/main/java/poomasi/domain/member/entity/Member.java +++ b/src/main/java/poomasi/domain/member/entity/Member.java @@ -10,7 +10,6 @@ import poomasi.domain.order.entity.Order; import poomasi.domain.store.entity.Store; import poomasi.domain.member._profile.entity.MemberProfile; -import poomasi.domain.store.entity.Store; import poomasi.domain.wishlist.entity.WishList; import poomasi.global.error.BusinessError; import poomasi.global.error.BusinessException; @@ -114,3 +113,4 @@ public Store getStore() { } } +//멤버에 농장, 스토어 두고 거기서 주솟값 가져오는 걸로 바꾸기 \ No newline at end of file diff --git a/src/main/java/poomasi/domain/member/service/MemberService.java b/src/main/java/poomasi/domain/member/service/MemberService.java index c386ee3c..f8ebdc02 100644 --- a/src/main/java/poomasi/domain/member/service/MemberService.java +++ b/src/main/java/poomasi/domain/member/service/MemberService.java @@ -7,6 +7,8 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import poomasi.domain.member.dto.request.CustomerUpdateRequest; +import poomasi.domain.member.dto.request.FarmerUpdateRequest; import poomasi.domain.member.dto.response.MemberResponse; import poomasi.domain.member.dto.response.MemberSummaryResponse; import poomasi.domain.member.entity.LoginType; @@ -16,6 +18,8 @@ import poomasi.domain.member.dto.response.SignUpResponse; import poomasi.global.error.BusinessException; +import java.util.Optional; + import static poomasi.domain.member.entity.Role.ROLE_CUSTOMER; import static poomasi.domain.member.entity.Role.ROLE_FARMER; import static poomasi.global.error.BusinessError.*; @@ -93,4 +97,23 @@ public Member findMemberById(Long memberId) { .orElseThrow(() -> new BusinessException(MEMBER_NOT_FOUND)); } + public Member updateCustomer(Member member, CustomerUpdateRequest customerUpdateRequest) + { + Optional.ofNullable(customerUpdateRequest.name()).ifPresent(member::setName); + Optional.ofNullable(customerUpdateRequest.email()).ifPresent(member::setEmail); + Optional.ofNullable(customerUpdateRequest.password()).ifPresent(member::setPassword); + + return memberRepository.save(member); + } + + public Member updateFarmer(Member member, FarmerUpdateRequest farmerUpdateRequest) + { + Optional.ofNullable(farmerUpdateRequest.name()).ifPresent(member::setName); + Optional.ofNullable(farmerUpdateRequest.email()).ifPresent(member::setEmail); + Optional.ofNullable(farmerUpdateRequest.password()).ifPresent(member::setPassword); + + + return memberRepository.save(member); + } + } From cd5b2cada89295981cad96c1efae2c9a21e02326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Sun, 10 Nov 2024 23:55:16 +0900 Subject: [PATCH 02/26] =?UTF-8?q?refactor:=20=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=ED=95=98=EB=82=98=EB=A1=9C=20?= =?UTF-8?q?=EB=8B=A8=EC=88=9C=ED=99=94=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/SecurityConfig.java | 2 +- .../dto/response/CommonProfileResponse.java | 14 +++--- .../dto/response/CustomerProfileResponse.java | 25 +++++----- .../dto/response/FarmerProfileResponse.java | 34 ++++---------- .../dto/response/MemberProfileResponse.java | 38 ++++++++++----- .../_profile/entity/CustomerProfile.java | 23 --------- .../member/_profile/entity/FarmerProfile.java | 47 ------------------- .../member/_profile/entity/MemberProfile.java | 30 +++++++++--- .../repository/MemberProfileRepository.java | 10 ---- .../poomasi/domain/member/entity/Member.java | 7 --- 10 files changed, 82 insertions(+), 148 deletions(-) delete mode 100644 src/main/java/poomasi/domain/member/_profile/entity/CustomerProfile.java delete mode 100644 src/main/java/poomasi/domain/member/_profile/entity/FarmerProfile.java diff --git a/src/main/java/poomasi/domain/auth/config/SecurityConfig.java b/src/main/java/poomasi/domain/auth/config/SecurityConfig.java index cb1a269b..4504a462 100644 --- a/src/main/java/poomasi/domain/auth/config/SecurityConfig.java +++ b/src/main/java/poomasi/domain/auth/config/SecurityConfig.java @@ -76,7 +76,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers(HttpMethod.GET, "/api/review/**").permitAll() .requestMatchers(HttpMethod.GET, "/health").permitAll() .requestMatchers(HttpMethod.GET, "/api/image/**").permitAll() - .requestMatchers("/api/sign-up", "/api/login", "api/reissue", "api/payment/**", "api/order/**", "api/reservation/**", "/api/v1/farmer/reservations").permitAll() + .requestMatchers("/api/member/sign-up", "/api/login", "api/reissue", "api/payment/**", "api/order/**", "api/reservation/**", "/api/v1/farmer/reservations").permitAll() .requestMatchers("/api/need-auth/**").authenticated() .anyRequest(). authenticated() diff --git a/src/main/java/poomasi/domain/member/_profile/dto/response/CommonProfileResponse.java b/src/main/java/poomasi/domain/member/_profile/dto/response/CommonProfileResponse.java index cb665655..5f6e24d6 100644 --- a/src/main/java/poomasi/domain/member/_profile/dto/response/CommonProfileResponse.java +++ b/src/main/java/poomasi/domain/member/_profile/dto/response/CommonProfileResponse.java @@ -1,18 +1,16 @@ package poomasi.domain.member._profile.dto.response; -import lombok.AllArgsConstructor; import poomasi.domain.image.entity.Image; import poomasi.domain.member._profile.entity.MemberProfile; import java.time.LocalDateTime; -@AllArgsConstructor -public class CommonProfileResponse implements MemberProfileResponse { - String phoneNumber; - boolean isBanned; - LocalDateTime createdAt; - Image profileImage; - +public record CommonProfileResponse ( + String phoneNumber, + boolean isBanned, + LocalDateTime createdAt, + Image profileImage +){ public static CommonProfileResponse fromEntity(MemberProfile profile) { return new CommonProfileResponse( profile.getPhoneNumber(), diff --git a/src/main/java/poomasi/domain/member/_profile/dto/response/CustomerProfileResponse.java b/src/main/java/poomasi/domain/member/_profile/dto/response/CustomerProfileResponse.java index 53501e03..d7dc0a81 100644 --- a/src/main/java/poomasi/domain/member/_profile/dto/response/CustomerProfileResponse.java +++ b/src/main/java/poomasi/domain/member/_profile/dto/response/CustomerProfileResponse.java @@ -1,25 +1,28 @@ package poomasi.domain.member._profile.dto.response; -import lombok.AllArgsConstructor; import poomasi.domain.image.entity.Image; -import poomasi.domain.member._profile.entity.CustomerProfile; +import poomasi.domain.member._profile.entity.MemberProfile; import java.time.LocalDateTime; -@AllArgsConstructor -public class CustomerProfileResponse implements MemberProfileResponse{ - String phoneNumber; - String address; - String addressDetail; - boolean isBanned; - LocalDateTime createdAt; - Image profileImage; +public record CustomerProfileResponse( + String phoneNumber, + String address, + String addressDetail, + Long coordinateX, + Long coordinateY, + boolean isBanned, + LocalDateTime createdAt, + Image profileImage){ - public static CustomerProfileResponse fromEntity(CustomerProfile profile) { + + public static CustomerProfileResponse fromEntity(MemberProfile profile) { return new CustomerProfileResponse( profile.getPhoneNumber(), profile.getAddress(), profile.getAddressDetail(), + profile.getCoordinateX(), + profile.getCoordinateY(), profile.isBanned(), profile.getCreatedAt(), profile.getProfileImage() diff --git a/src/main/java/poomasi/domain/member/_profile/dto/response/FarmerProfileResponse.java b/src/main/java/poomasi/domain/member/_profile/dto/response/FarmerProfileResponse.java index 53fed2f5..cd0ec824 100644 --- a/src/main/java/poomasi/domain/member/_profile/dto/response/FarmerProfileResponse.java +++ b/src/main/java/poomasi/domain/member/_profile/dto/response/FarmerProfileResponse.java @@ -1,39 +1,25 @@ package poomasi.domain.member._profile.dto.response; -import lombok.AllArgsConstructor; import poomasi.domain.image.entity.Image; -import poomasi.domain.member._profile.entity.FarmerProfile; +import poomasi.domain.member._profile.entity.MemberProfile; import java.time.LocalDateTime; import java.util.List; -@AllArgsConstructor -public class FarmerProfileResponse implements MemberProfileResponse { - String phoneNumber; - boolean isBanned; - LocalDateTime createdAt; - Image profileImage; - String storeName; - String farmName; - List businessRegistrationNumbers; - String storeAddress; - String storeAddressDetail; - String farmAddress; - String farmAddressDetail; - - public static FarmerProfileResponse fromEntity(FarmerProfile profile) { +public record FarmerProfileResponse( + String phoneNumber, + boolean isBanned, + LocalDateTime createdAt, + Image profileImage, + List businessRegistrationNumbers +){ + public static FarmerProfileResponse fromEntity(MemberProfile profile) { return new FarmerProfileResponse( profile.getPhoneNumber(), profile.isBanned(), profile.getCreatedAt(), profile.getProfileImage(), - profile.getStoreName(), - profile.getFarmName(), - profile.getBusinessRegistrationNumbers(), - profile.getStoreAddress(), - profile.getStoreAddressDetail(), - profile.getFarmAddress(), - profile.getFarmAddressDetail() + profile.getBusinessRegistrationNumbers() ); } } \ No newline at end of file diff --git a/src/main/java/poomasi/domain/member/_profile/dto/response/MemberProfileResponse.java b/src/main/java/poomasi/domain/member/_profile/dto/response/MemberProfileResponse.java index b191dda0..1c0b7c3a 100644 --- a/src/main/java/poomasi/domain/member/_profile/dto/response/MemberProfileResponse.java +++ b/src/main/java/poomasi/domain/member/_profile/dto/response/MemberProfileResponse.java @@ -1,18 +1,34 @@ package poomasi.domain.member._profile.dto.response; -import poomasi.domain.member._profile.entity.CustomerProfile; -import poomasi.domain.member._profile.entity.FarmerProfile; +import poomasi.domain.image.entity.Image; import poomasi.domain.member._profile.entity.MemberProfile; -public interface MemberProfileResponse { +import java.time.LocalDateTime; +import java.util.List; - static MemberProfileResponse fromEntity(MemberProfile profile) { - if (profile instanceof FarmerProfile farmerProfile) { - return FarmerProfileResponse.fromEntity(farmerProfile); - } else if (profile instanceof CustomerProfile customerProfile) { - return CustomerProfileResponse.fromEntity(customerProfile); - } else { - return CommonProfileResponse.fromEntity(profile); - } +public record MemberProfileResponse( + String phoneNumber, + String address, + String addressDetail, + Long coordinateX, + Long coordinateY, + List businessRegistrationNumbers, + boolean isBanned, + LocalDateTime createdAt, + Image profileImage){ + + + public static MemberProfileResponse fromEntity(MemberProfile profile) { + return new MemberProfileResponse( + profile.getPhoneNumber(), + profile.getAddress(), + profile.getAddressDetail(), + profile.getCoordinateX(), + profile.getCoordinateY(), + profile.getBusinessRegistrationNumbers(), + profile.isBanned(), + profile.getCreatedAt(), + profile.getProfileImage() + ); } } \ No newline at end of file diff --git a/src/main/java/poomasi/domain/member/_profile/entity/CustomerProfile.java b/src/main/java/poomasi/domain/member/_profile/entity/CustomerProfile.java deleted file mode 100644 index ea7b83ad..00000000 --- a/src/main/java/poomasi/domain/member/_profile/entity/CustomerProfile.java +++ /dev/null @@ -1,23 +0,0 @@ -package poomasi.domain.member._profile.entity; - -import jakarta.persistence.Column; -import jakarta.persistence.DiscriminatorValue; -import jakarta.persistence.Entity; -import lombok.Getter; - -@Entity -@Getter -@DiscriminatorValue("CUSTOMER") -public class CustomerProfile extends MemberProfile{ - @Column(nullable = true, length = 255) - private String address; - - @Column(nullable = true, length = 255) - private String addressDetail; - - @Column(nullable=true, length=255) - private Long coordinateX; - - @Column(nullable=true, length=255) - private Long coordinateY; -} diff --git a/src/main/java/poomasi/domain/member/_profile/entity/FarmerProfile.java b/src/main/java/poomasi/domain/member/_profile/entity/FarmerProfile.java deleted file mode 100644 index 06b946c7..00000000 --- a/src/main/java/poomasi/domain/member/_profile/entity/FarmerProfile.java +++ /dev/null @@ -1,47 +0,0 @@ -package poomasi.domain.member._profile.entity; - -import jakarta.persistence.*; -import lombok.Getter; - -import java.util.List; - -@Entity -@Getter -@DiscriminatorValue("FARMER") -public class FarmerProfile extends MemberProfile{ - @Column(nullable = true, length = 100, unique = true) - private String storeName; - - @Column(nullable = true, length = 100) - private String storeAddress; - - @Column(nullable = true, length = 100) - private String storeAddressDetail; - - @Column(nullable=true, length=100) - private Long storeCoordinateX; - - @Column(nullable=true, length=100) - private Long storeCoordinateY; - - @Column(nullable = true, length = 100, unique = true) - private String farmName; - - @Column(nullable = true, length = 100) - private String farmAddress; - - @Column(nullable = true, length = 100) - private String farmAddressDetail; - - @Column(nullable=true, length=100) - private Long farmCoordinateX; - - @Column(nullable=true, length=100) - private Long farmCoordinateY; - - @ElementCollection - @CollectionTable(name = "business_registration_numbers", joinColumns = @JoinColumn(name = "farmer_profile_id")) - @Column(nullable = true, length=255) - private List businessRegistrationNumbers; - -} diff --git a/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java b/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java index af2b5849..9911dab2 100644 --- a/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java +++ b/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java @@ -6,14 +6,13 @@ import poomasi.domain.member.entity.Member; import java.time.LocalDateTime; +import java.util.List; @Getter @Entity @Table(name = "member_profile") @AllArgsConstructor @Builder -@Inheritance(strategy = InheritanceType.JOINED) -@DiscriminatorColumn(name = "profile_type") public class MemberProfile { @Id @@ -35,10 +34,29 @@ public class MemberProfile { @JoinColumn(name = "profile_image_id") private Image profileImage; - @Setter - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id", referencedColumnName = "id") - private Member member; + // customer인 경우 + @Column(nullable = true, length = 255) + private String address; + + @Column(nullable = true, length = 255) + private String addressDetail; + + @Column(nullable=true, length=255) + private Long coordinateX; + + @Column(nullable=true, length=255) + private Long coordinateY; + + // farmer인 경우 + @ElementCollection + @CollectionTable(name = "business_registration_numbers", joinColumns = @JoinColumn(name = "farmer_profile_id")) + @Column(nullable = true, length=255) + private List businessRegistrationNumbers; + +// @Setter +// @OneToOne(fetch = FetchType.LAZY) +// @JoinColumn(name = "member_id", referencedColumnName = "id") +// private Member member; @PrePersist public void prePersist() { diff --git a/src/main/java/poomasi/domain/member/_profile/repository/MemberProfileRepository.java b/src/main/java/poomasi/domain/member/_profile/repository/MemberProfileRepository.java index f59a2490..433f671c 100644 --- a/src/main/java/poomasi/domain/member/_profile/repository/MemberProfileRepository.java +++ b/src/main/java/poomasi/domain/member/_profile/repository/MemberProfileRepository.java @@ -1,19 +1,9 @@ package poomasi.domain.member._profile.repository; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import poomasi.domain.member._profile.entity.FarmerProfile; import poomasi.domain.member._profile.entity.MemberProfile; -import java.util.Optional; - @Repository public interface MemberProfileRepository extends JpaRepository { - - // FarmerProfile 타입만 조회 -// @Query("SELECT p FROM FarmerProfile p WHERE p.farmName = :farmName") -// Optional findFarmerByFarmName(@Param("farmName") String farmName); - } \ No newline at end of file diff --git a/src/main/java/poomasi/domain/member/entity/Member.java b/src/main/java/poomasi/domain/member/entity/Member.java index 67bc9ee8..c23cf09f 100644 --- a/src/main/java/poomasi/domain/member/entity/Member.java +++ b/src/main/java/poomasi/domain/member/entity/Member.java @@ -76,13 +76,6 @@ public Member(String name, String email, String password, LoginType loginType, R this.role = role; } - public void setMemberProfile(MemberProfile memberProfile) { - this.memberProfile = memberProfile; - if (memberProfile != null) { - memberProfile.setMember(this); - } - } - @Builder public Member(Long id, String email, String password, Role role, LoginType loginType, String provideId, MemberProfile memberProfile) { this.id = id; From 902b6a5b36a4cc9cf0fd737dc254a15b778217da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 00:09:44 +0900 Subject: [PATCH 03/26] =?UTF-8?q?refactor:=20=EB=86=8D=EB=B6=80=EB=A1=9C?= =?UTF-8?q?=20=EC=A0=84=ED=99=98=20=EC=9D=B8=EC=9E=90=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../poomasi/domain/member/controller/MemberController.java | 6 ++---- .../member/dto/request/FarmerQualificationRequest.java | 3 --- src/main/java/poomasi/domain/member/entity/Member.java | 5 ++--- .../java/poomasi/domain/member/service/MemberService.java | 6 +----- 4 files changed, 5 insertions(+), 15 deletions(-) delete mode 100644 src/main/java/poomasi/domain/member/dto/request/FarmerQualificationRequest.java diff --git a/src/main/java/poomasi/domain/member/controller/MemberController.java b/src/main/java/poomasi/domain/member/controller/MemberController.java index ad38dce9..2f56ba02 100644 --- a/src/main/java/poomasi/domain/member/controller/MemberController.java +++ b/src/main/java/poomasi/domain/member/controller/MemberController.java @@ -10,7 +10,6 @@ import org.springframework.web.bind.annotation.*; import poomasi.domain.auth.security.userdetail.UserDetailsImpl; import poomasi.domain.member.dto.request.CustomerUpdateRequest; -import poomasi.domain.member.dto.request.FarmerQualificationRequest; import poomasi.domain.member.dto.request.FarmerUpdateRequest; import poomasi.domain.member.dto.response.MemberResponse; import poomasi.domain.member.dto.response.MemberSummaryResponse; @@ -34,10 +33,9 @@ public ResponseEntity signUp(@RequestBody SignupRequest signupRe @PutMapping("/toFarmer") @Secured("ROLE_CUSTOMER") - public ResponseEntity convertToFarmer(@AuthenticationPrincipal UserDetailsImpl userDetails, - @RequestBody FarmerQualificationRequest request) { + public ResponseEntity convertToFarmer(@AuthenticationPrincipal UserDetailsImpl userDetails) { Member member = userDetails.getMember(); - memberService.convertToFarmer(member, request.hasFarmerQualification()); + memberService.convertToFarmer(member); return ResponseEntity.noContent().build(); } diff --git a/src/main/java/poomasi/domain/member/dto/request/FarmerQualificationRequest.java b/src/main/java/poomasi/domain/member/dto/request/FarmerQualificationRequest.java deleted file mode 100644 index d4e6147d..00000000 --- a/src/main/java/poomasi/domain/member/dto/request/FarmerQualificationRequest.java +++ /dev/null @@ -1,3 +0,0 @@ -package poomasi.domain.member.dto.request; - -public record FarmerQualificationRequest(Boolean hasFarmerQualification) {} diff --git a/src/main/java/poomasi/domain/member/entity/Member.java b/src/main/java/poomasi/domain/member/entity/Member.java index c23cf09f..cac316b8 100644 --- a/src/main/java/poomasi/domain/member/entity/Member.java +++ b/src/main/java/poomasi/domain/member/entity/Member.java @@ -66,7 +66,7 @@ public class Member { @Setter @OneToOne(mappedBy="owner", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - Store store; + private Store store; public Member(String name, String email, String password, LoginType loginType, Role role) { this.name = name; @@ -77,14 +77,13 @@ public Member(String name, String email, String password, LoginType loginType, R } @Builder - public Member(Long id, String email, String password, Role role, LoginType loginType, String provideId, MemberProfile memberProfile) { + public Member(Long id, String email, String password, Role role, LoginType loginType, String provideId) { this.id = id; this.password = password; this.email = email; this.role = role; this.loginType = loginType; this.provideId = provideId; - this.memberProfile = memberProfile; } public boolean isCustomer() { diff --git a/src/main/java/poomasi/domain/member/service/MemberService.java b/src/main/java/poomasi/domain/member/service/MemberService.java index f8ebdc02..2d39101d 100644 --- a/src/main/java/poomasi/domain/member/service/MemberService.java +++ b/src/main/java/poomasi/domain/member/service/MemberService.java @@ -67,15 +67,11 @@ public Page getAllMembersSummary(Pageable pageable) { } @Transactional - public void convertToFarmer(Member member, Boolean hasFarmerQualification) { + public void convertToFarmer(Member member) { if (member.isFarmer()) { throw new BusinessException(MEMBER_ALREADY_FARMER); } - if (!hasFarmerQualification) { - throw new BusinessException(INVALID_FARMER_QUALIFICATION); - } - member.setRole(ROLE_FARMER); memberRepository.save(member); } From 6f819c396485b46d59daa290afe6eac8fd12029f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 00:14:03 +0900 Subject: [PATCH 04/26] =?UTF-8?q?refactor:=20MemberSummaryResponse=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/dto/response/MemberSummaryResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/poomasi/domain/member/dto/response/MemberSummaryResponse.java b/src/main/java/poomasi/domain/member/dto/response/MemberSummaryResponse.java index f57c1bfa..e26fa705 100644 --- a/src/main/java/poomasi/domain/member/dto/response/MemberSummaryResponse.java +++ b/src/main/java/poomasi/domain/member/dto/response/MemberSummaryResponse.java @@ -7,7 +7,7 @@ public record MemberSummaryResponse(String name, Image profileImage) { public static MemberSummaryResponse fromEntity(Member member) { return new MemberSummaryResponse( member.getName(), - member.getMemberProfile().getProfileImage() + member.getMemberProfile() != null ? member.getMemberProfile().getProfileImage() : null ); } } From 37ce7ed9cd4d5e912d0f17689e004fbc204761d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 00:26:34 +0900 Subject: [PATCH 05/26] =?UTF-8?q?feat:=20CustomerResponse,=20FarmerRespons?= =?UTF-8?q?e=20=EC=83=9D=EC=84=B1=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 12 +++++----- .../member/dto/response/CustomerResponse.java | 22 +++++++++++++++++++ .../member/dto/response/FarmerResponse.java | 22 +++++++++++++++++++ .../poomasi/domain/member/entity/Member.java | 3 +++ 4 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 src/main/java/poomasi/domain/member/dto/response/CustomerResponse.java create mode 100644 src/main/java/poomasi/domain/member/dto/response/FarmerResponse.java diff --git a/src/main/java/poomasi/domain/member/controller/MemberController.java b/src/main/java/poomasi/domain/member/controller/MemberController.java index 2f56ba02..0437c33d 100644 --- a/src/main/java/poomasi/domain/member/controller/MemberController.java +++ b/src/main/java/poomasi/domain/member/controller/MemberController.java @@ -11,12 +11,10 @@ import poomasi.domain.auth.security.userdetail.UserDetailsImpl; import poomasi.domain.member.dto.request.CustomerUpdateRequest; import poomasi.domain.member.dto.request.FarmerUpdateRequest; -import poomasi.domain.member.dto.response.MemberResponse; -import poomasi.domain.member.dto.response.MemberSummaryResponse; +import poomasi.domain.member.dto.response.*; import poomasi.domain.member.entity.Member; import poomasi.domain.member.service.MemberService; import poomasi.domain.member.dto.request.SignupRequest; -import poomasi.domain.member.dto.response.SignUpResponse; @RestController @RequiredArgsConstructor @@ -77,27 +75,27 @@ public ResponseEntity getMemberSummaryById(@PathVariable @PutMapping("/customer/update") @Secured("ROLE_CUSTOMER") - public ResponseEntity updateCustomer( + public ResponseEntity updateCustomer( @AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody CustomerUpdateRequest customerUpdateRequest) { Member member = userDetails.getMember(); Member updatedMember = memberService.updateCustomer(member, customerUpdateRequest); - MemberResponse memberResponse = MemberResponse.fromEntity(updatedMember); + CustomerResponse memberResponse = CustomerResponse.fromEntity(updatedMember); return ResponseEntity.ok(memberResponse); } @PutMapping("/farmer/update") @Secured("ROLE_FARMER") - public ResponseEntity updateFarmer( + public ResponseEntity updateFarmer( @AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody FarmerUpdateRequest farmerUpdateRequest) { Member member = userDetails.getMember(); Member updatedMember = memberService.updateFarmer(member, farmerUpdateRequest); - MemberResponse memberResponse = MemberResponse.fromEntity(updatedMember); + FarmerResponse memberResponse = FarmerResponse.fromEntity(updatedMember); return ResponseEntity.ok(memberResponse); } diff --git a/src/main/java/poomasi/domain/member/dto/response/CustomerResponse.java b/src/main/java/poomasi/domain/member/dto/response/CustomerResponse.java new file mode 100644 index 00000000..76b0c800 --- /dev/null +++ b/src/main/java/poomasi/domain/member/dto/response/CustomerResponse.java @@ -0,0 +1,22 @@ +package poomasi.domain.member.dto.response; + +import poomasi.domain.member._profile.dto.response.CustomerProfileResponse; +import poomasi.domain.member.entity.Member; + +public record CustomerResponse( + Long id, + String name, + String email, + String role, + CustomerProfileResponse memberProfile +) { + public static CustomerResponse fromEntity(Member member) { + return new CustomerResponse( + member.getId(), + member.getName(), + member.getEmail(), + member.getRole().name(), + member.getMemberProfile() != null ? CustomerProfileResponse.fromEntity(member.getMemberProfile()) : null + ); + } +} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/member/dto/response/FarmerResponse.java b/src/main/java/poomasi/domain/member/dto/response/FarmerResponse.java new file mode 100644 index 00000000..4544c1eb --- /dev/null +++ b/src/main/java/poomasi/domain/member/dto/response/FarmerResponse.java @@ -0,0 +1,22 @@ +package poomasi.domain.member.dto.response; + +import poomasi.domain.member._profile.dto.response.FarmerProfileResponse; +import poomasi.domain.member.entity.Member; + +public record FarmerResponse( + Long id, + String name, + String email, + String role, + FarmerProfileResponse memberProfile +) { + public static FarmerResponse fromEntity(Member member) { + return new FarmerResponse( + member.getId(), + member.getName(), + member.getEmail(), + member.getRole().name(), + member.getMemberProfile() != null ? FarmerProfileResponse.fromEntity(member.getMemberProfile()) : null + ); + } +} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/member/entity/Member.java b/src/main/java/poomasi/domain/member/entity/Member.java index cac316b8..ed18c274 100644 --- a/src/main/java/poomasi/domain/member/entity/Member.java +++ b/src/main/java/poomasi/domain/member/entity/Member.java @@ -26,12 +26,15 @@ public class Member { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Setter @Column(nullable = true, length = 50) private String name; + @Setter @Column(unique = true, nullable = true, length = 50) private String email; + @Setter @Column(nullable = true) private String password; From 6e2f82f4c7668a4cd694a05a720bd6e73d435a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 01:08:54 +0900 Subject: [PATCH 06/26] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90,=20=EB=86=8D?= =?UTF-8?q?=EB=B6=80=20=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/CommonProfileResponse.java | 23 ------------ .../dto/response/CustomerProfileResponse.java | 31 ---------------- .../dto/response/FarmerProfileResponse.java | 7 +--- .../dto/response/MemberProfileResponse.java | 7 +--- .../member/_profile/entity/MemberProfile.java | 18 ++------- .../member/controller/MemberController.java | 4 +- .../dto/request/FarmerUpdateRequest.java | 3 +- .../member/dto/response/CustomerResponse.java | 22 ----------- .../poomasi/domain/member/entity/Member.java | 17 +++++++++ .../domain/member/service/MemberService.java | 37 ++++++++++++++++--- .../poomasi/domain/store/entity/Store.java | 6 +++ .../poomasi/global/error/BusinessError.java | 1 + 12 files changed, 65 insertions(+), 111 deletions(-) delete mode 100644 src/main/java/poomasi/domain/member/_profile/dto/response/CommonProfileResponse.java delete mode 100644 src/main/java/poomasi/domain/member/_profile/dto/response/CustomerProfileResponse.java delete mode 100644 src/main/java/poomasi/domain/member/dto/response/CustomerResponse.java diff --git a/src/main/java/poomasi/domain/member/_profile/dto/response/CommonProfileResponse.java b/src/main/java/poomasi/domain/member/_profile/dto/response/CommonProfileResponse.java deleted file mode 100644 index 5f6e24d6..00000000 --- a/src/main/java/poomasi/domain/member/_profile/dto/response/CommonProfileResponse.java +++ /dev/null @@ -1,23 +0,0 @@ -package poomasi.domain.member._profile.dto.response; - -import poomasi.domain.image.entity.Image; -import poomasi.domain.member._profile.entity.MemberProfile; - -import java.time.LocalDateTime; - -public record CommonProfileResponse ( - String phoneNumber, - boolean isBanned, - LocalDateTime createdAt, - Image profileImage -){ - public static CommonProfileResponse fromEntity(MemberProfile profile) { - return new CommonProfileResponse( - profile.getPhoneNumber(), - profile.isBanned(), - profile.getCreatedAt(), - profile.getProfileImage() - ); - } - -} diff --git a/src/main/java/poomasi/domain/member/_profile/dto/response/CustomerProfileResponse.java b/src/main/java/poomasi/domain/member/_profile/dto/response/CustomerProfileResponse.java deleted file mode 100644 index d7dc0a81..00000000 --- a/src/main/java/poomasi/domain/member/_profile/dto/response/CustomerProfileResponse.java +++ /dev/null @@ -1,31 +0,0 @@ -package poomasi.domain.member._profile.dto.response; - -import poomasi.domain.image.entity.Image; -import poomasi.domain.member._profile.entity.MemberProfile; - -import java.time.LocalDateTime; - -public record CustomerProfileResponse( - String phoneNumber, - String address, - String addressDetail, - Long coordinateX, - Long coordinateY, - boolean isBanned, - LocalDateTime createdAt, - Image profileImage){ - - - public static CustomerProfileResponse fromEntity(MemberProfile profile) { - return new CustomerProfileResponse( - profile.getPhoneNumber(), - profile.getAddress(), - profile.getAddressDetail(), - profile.getCoordinateX(), - profile.getCoordinateY(), - profile.isBanned(), - profile.getCreatedAt(), - profile.getProfileImage() - ); - } -} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/member/_profile/dto/response/FarmerProfileResponse.java b/src/main/java/poomasi/domain/member/_profile/dto/response/FarmerProfileResponse.java index cd0ec824..ec11888f 100644 --- a/src/main/java/poomasi/domain/member/_profile/dto/response/FarmerProfileResponse.java +++ b/src/main/java/poomasi/domain/member/_profile/dto/response/FarmerProfileResponse.java @@ -4,22 +4,19 @@ import poomasi.domain.member._profile.entity.MemberProfile; import java.time.LocalDateTime; -import java.util.List; public record FarmerProfileResponse( String phoneNumber, boolean isBanned, LocalDateTime createdAt, - Image profileImage, - List businessRegistrationNumbers + Image profileImage ){ public static FarmerProfileResponse fromEntity(MemberProfile profile) { return new FarmerProfileResponse( profile.getPhoneNumber(), profile.isBanned(), profile.getCreatedAt(), - profile.getProfileImage(), - profile.getBusinessRegistrationNumbers() + profile.getProfileImage() ); } } \ No newline at end of file diff --git a/src/main/java/poomasi/domain/member/_profile/dto/response/MemberProfileResponse.java b/src/main/java/poomasi/domain/member/_profile/dto/response/MemberProfileResponse.java index 1c0b7c3a..691d8673 100644 --- a/src/main/java/poomasi/domain/member/_profile/dto/response/MemberProfileResponse.java +++ b/src/main/java/poomasi/domain/member/_profile/dto/response/MemberProfileResponse.java @@ -4,15 +4,13 @@ import poomasi.domain.member._profile.entity.MemberProfile; import java.time.LocalDateTime; -import java.util.List; public record MemberProfileResponse( String phoneNumber, - String address, + String defaultAddress, String addressDetail, Long coordinateX, Long coordinateY, - List businessRegistrationNumbers, boolean isBanned, LocalDateTime createdAt, Image profileImage){ @@ -21,11 +19,10 @@ public record MemberProfileResponse( public static MemberProfileResponse fromEntity(MemberProfile profile) { return new MemberProfileResponse( profile.getPhoneNumber(), - profile.getAddress(), + profile.getDefaultAddress(), profile.getAddressDetail(), profile.getCoordinateX(), profile.getCoordinateY(), - profile.getBusinessRegistrationNumbers(), profile.isBanned(), profile.getCreatedAt(), profile.getProfileImage() diff --git a/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java b/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java index 9911dab2..7fc0f0be 100644 --- a/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java +++ b/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java @@ -3,10 +3,8 @@ import jakarta.persistence.*; import lombok.*; import poomasi.domain.image.entity.Image; -import poomasi.domain.member.entity.Member; import java.time.LocalDateTime; -import java.util.List; @Getter @Entity @@ -19,6 +17,7 @@ public class MemberProfile { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Setter @Column(nullable = true, length = 20) private String phoneNumber; @@ -34,9 +33,9 @@ public class MemberProfile { @JoinColumn(name = "profile_image_id") private Image profileImage; - // customer인 경우 + // 기본 배송지 @Column(nullable = true, length = 255) - private String address; + private String defaultAddress; @Column(nullable = true, length = 255) private String addressDetail; @@ -47,17 +46,6 @@ public class MemberProfile { @Column(nullable=true, length=255) private Long coordinateY; - // farmer인 경우 - @ElementCollection - @CollectionTable(name = "business_registration_numbers", joinColumns = @JoinColumn(name = "farmer_profile_id")) - @Column(nullable = true, length=255) - private List businessRegistrationNumbers; - -// @Setter -// @OneToOne(fetch = FetchType.LAZY) -// @JoinColumn(name = "member_id", referencedColumnName = "id") -// private Member member; - @PrePersist public void prePersist() { this.createdAt = LocalDateTime.now(); diff --git a/src/main/java/poomasi/domain/member/controller/MemberController.java b/src/main/java/poomasi/domain/member/controller/MemberController.java index 0437c33d..8d6aa8e4 100644 --- a/src/main/java/poomasi/domain/member/controller/MemberController.java +++ b/src/main/java/poomasi/domain/member/controller/MemberController.java @@ -75,14 +75,14 @@ public ResponseEntity getMemberSummaryById(@PathVariable @PutMapping("/customer/update") @Secured("ROLE_CUSTOMER") - public ResponseEntity updateCustomer( + public ResponseEntity updateCustomer( @AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody CustomerUpdateRequest customerUpdateRequest) { Member member = userDetails.getMember(); Member updatedMember = memberService.updateCustomer(member, customerUpdateRequest); - CustomerResponse memberResponse = CustomerResponse.fromEntity(updatedMember); + MemberResponse memberResponse = MemberResponse.fromEntity(updatedMember); return ResponseEntity.ok(memberResponse); } diff --git a/src/main/java/poomasi/domain/member/dto/request/FarmerUpdateRequest.java b/src/main/java/poomasi/domain/member/dto/request/FarmerUpdateRequest.java index 3cac6814..3e16d19a 100644 --- a/src/main/java/poomasi/domain/member/dto/request/FarmerUpdateRequest.java +++ b/src/main/java/poomasi/domain/member/dto/request/FarmerUpdateRequest.java @@ -6,6 +6,5 @@ public record FarmerUpdateRequest( String password, String phoneNumber, String storeName, - String storeAddress, - String storeAddressDetail) { + String storeAddress) { } diff --git a/src/main/java/poomasi/domain/member/dto/response/CustomerResponse.java b/src/main/java/poomasi/domain/member/dto/response/CustomerResponse.java deleted file mode 100644 index 76b0c800..00000000 --- a/src/main/java/poomasi/domain/member/dto/response/CustomerResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package poomasi.domain.member.dto.response; - -import poomasi.domain.member._profile.dto.response.CustomerProfileResponse; -import poomasi.domain.member.entity.Member; - -public record CustomerResponse( - Long id, - String name, - String email, - String role, - CustomerProfileResponse memberProfile -) { - public static CustomerResponse fromEntity(Member member) { - return new CustomerResponse( - member.getId(), - member.getName(), - member.getEmail(), - member.getRole().name(), - member.getMemberProfile() != null ? CustomerProfileResponse.fromEntity(member.getMemberProfile()) : null - ); - } -} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/member/entity/Member.java b/src/main/java/poomasi/domain/member/entity/Member.java index ed18c274..2517f363 100644 --- a/src/main/java/poomasi/domain/member/entity/Member.java +++ b/src/main/java/poomasi/domain/member/entity/Member.java @@ -107,5 +107,22 @@ public Store getStore() { return store; } + public MemberProfile getOrCreateProfile() { + if (this.memberProfile == null) { + this.memberProfile = new MemberProfile(); + } + return memberProfile; + } + + public Store getOrCreateStore() { + if (this.store == null) { + this.store = new Store(); + this.store.setOwner(this); + } + return store; + } + + + } //멤버에 농장, 스토어 두고 거기서 주솟값 가져오는 걸로 바꾸기 \ No newline at end of file diff --git a/src/main/java/poomasi/domain/member/service/MemberService.java b/src/main/java/poomasi/domain/member/service/MemberService.java index 2d39101d..fe8b9eb2 100644 --- a/src/main/java/poomasi/domain/member/service/MemberService.java +++ b/src/main/java/poomasi/domain/member/service/MemberService.java @@ -7,6 +7,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import poomasi.domain.member._profile.entity.MemberProfile; import poomasi.domain.member.dto.request.CustomerUpdateRequest; import poomasi.domain.member.dto.request.FarmerUpdateRequest; import poomasi.domain.member.dto.response.MemberResponse; @@ -16,6 +17,7 @@ import poomasi.domain.member.repository.MemberRepository; import poomasi.domain.member.dto.request.SignupRequest; import poomasi.domain.member.dto.response.SignUpResponse; +import poomasi.domain.store.entity.Store; import poomasi.global.error.BusinessException; import java.util.Optional; @@ -95,21 +97,44 @@ public Member findMemberById(Long memberId) { public Member updateCustomer(Member member, CustomerUpdateRequest customerUpdateRequest) { - Optional.ofNullable(customerUpdateRequest.name()).ifPresent(member::setName); - Optional.ofNullable(customerUpdateRequest.email()).ifPresent(member::setEmail); - Optional.ofNullable(customerUpdateRequest.password()).ifPresent(member::setPassword); + if (!member.isCustomer()) { + throw new BusinessException(INVALID_ROLE); + } + + updateCommonAttributes(member, customerUpdateRequest.name(),customerUpdateRequest.email(), customerUpdateRequest.password()); return memberRepository.save(member); } public Member updateFarmer(Member member, FarmerUpdateRequest farmerUpdateRequest) { - Optional.ofNullable(farmerUpdateRequest.name()).ifPresent(member::setName); - Optional.ofNullable(farmerUpdateRequest.email()).ifPresent(member::setEmail); - Optional.ofNullable(farmerUpdateRequest.password()).ifPresent(member::setPassword); + if (!member.isFarmer()) { + throw new BusinessException(INVALID_ROLE); + } + + updateCommonAttributes(member, farmerUpdateRequest.name(), farmerUpdateRequest.email(), farmerUpdateRequest.password()); + + MemberProfile profile = member.getOrCreateProfile(); + + Optional.ofNullable(farmerUpdateRequest.phoneNumber()).ifPresent(profile::setPhoneNumber); + + Store store = member.getOrCreateStore(); + + if (farmerUpdateRequest.storeName() != null) { + store.setName(farmerUpdateRequest.storeName()); + } + if (farmerUpdateRequest.storeAddress() != null) { + store.setAddress(farmerUpdateRequest.storeAddress()); + } return memberRepository.save(member); } + private void updateCommonAttributes(Member member, String name, String email, String password) { + if (name != null) member.setName(name); + if (email != null) member.setEmail(email); + if (password != null) member.setPassword(passwordEncoder.encode(password)); + } + } diff --git a/src/main/java/poomasi/domain/store/entity/Store.java b/src/main/java/poomasi/domain/store/entity/Store.java index c4be3f96..84d24c95 100644 --- a/src/main/java/poomasi/domain/store/entity/Store.java +++ b/src/main/java/poomasi/domain/store/entity/Store.java @@ -13,6 +13,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import org.hibernate.annotations.Comment; import poomasi.domain.member.entity.Member; import poomasi.domain.store.dto.StoreRegisterRequest; @@ -26,10 +27,15 @@ public class Store { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Setter private String name; + + @Setter private String address; private String phone; + @Setter @OneToOne(fetch = FetchType.LAZY) private Member owner; diff --git a/src/main/java/poomasi/global/error/BusinessError.java b/src/main/java/poomasi/global/error/BusinessError.java index 67d668d4..b4bd8a56 100644 --- a/src/main/java/poomasi/global/error/BusinessError.java +++ b/src/main/java/poomasi/global/error/BusinessError.java @@ -24,6 +24,7 @@ public enum BusinessError { MEMBER_ALREADY_CUSTOMER(HttpStatus.BAD_REQUEST, "이미 고객인 회원입니다."), MEMBER_ALREADY_FARMER(HttpStatus.BAD_REQUEST, "이미 농부인 회원입니다."), MEMBER_ID_MISMATCH(HttpStatus.FORBIDDEN, "권한이 없는 요청입니다."), + INVALID_ROLE(HttpStatus.FORBIDDEN, "권한이 없는 요청입니다."), // MemberProfile MEMBER_PROFILE_NOT_FOUND(HttpStatus.NOT_FOUND, "회원 세부 정보가 존재하지 않습니다."), From 3730a3736d9a850aeae190ade6e0217b8b1aa174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 03:07:45 +0900 Subject: [PATCH 07/26] =?UTF-8?q?feat:=20=EB=B0=B0=EC=86=A1=EC=A7=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MemberProfileController.java | 14 -------------- .../dto/request/AddressUpdateRequest.java | 8 ++++++++ .../dto/request/MemberProfileRequest.java | 5 ----- .../member/_profile/entity/MemberProfile.java | 17 +++++++++++++++++ .../member/controller/MemberController.java | 18 ++++++++++++++++++ .../poomasi/domain/member/entity/Member.java | 4 +++- .../domain/member/service/MemberService.java | 17 +++++++++++++++-- 7 files changed, 61 insertions(+), 22 deletions(-) delete mode 100644 src/main/java/poomasi/domain/member/_profile/controller/MemberProfileController.java create mode 100644 src/main/java/poomasi/domain/member/_profile/dto/request/AddressUpdateRequest.java delete mode 100644 src/main/java/poomasi/domain/member/_profile/dto/request/MemberProfileRequest.java diff --git a/src/main/java/poomasi/domain/member/_profile/controller/MemberProfileController.java b/src/main/java/poomasi/domain/member/_profile/controller/MemberProfileController.java deleted file mode 100644 index 97de1cdf..00000000 --- a/src/main/java/poomasi/domain/member/_profile/controller/MemberProfileController.java +++ /dev/null @@ -1,14 +0,0 @@ -package poomasi.domain.member._profile.controller; - -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import poomasi.domain.member._profile.service.MemberProfileService; - -@RestController -@RequiredArgsConstructor -@RequestMapping("api/member/profile") -public class MemberProfileController { - - private final MemberProfileService memberProfileService; -} diff --git a/src/main/java/poomasi/domain/member/_profile/dto/request/AddressUpdateRequest.java b/src/main/java/poomasi/domain/member/_profile/dto/request/AddressUpdateRequest.java new file mode 100644 index 00000000..8a8ac1d0 --- /dev/null +++ b/src/main/java/poomasi/domain/member/_profile/dto/request/AddressUpdateRequest.java @@ -0,0 +1,8 @@ +package poomasi.domain.member._profile.dto.request; + +public record AddressUpdateRequest( + String defaultAddress, + String addressDetail, + Long coordinateX, + Long coordinateY) { +} diff --git a/src/main/java/poomasi/domain/member/_profile/dto/request/MemberProfileRequest.java b/src/main/java/poomasi/domain/member/_profile/dto/request/MemberProfileRequest.java deleted file mode 100644 index 3492e58d..00000000 --- a/src/main/java/poomasi/domain/member/_profile/dto/request/MemberProfileRequest.java +++ /dev/null @@ -1,5 +0,0 @@ -package poomasi.domain.member._profile.dto.request; - - -public record MemberProfileRequest() { -} diff --git a/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java b/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java index 7fc0f0be..5bec6761 100644 --- a/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java +++ b/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java @@ -2,6 +2,7 @@ import jakarta.persistence.*; import lombok.*; +import org.hibernate.annotations.SQLDelete; import poomasi.domain.image.entity.Image; import java.time.LocalDateTime; @@ -11,6 +12,7 @@ @Table(name = "member_profile") @AllArgsConstructor @Builder +@SQLDelete(sql = "UPDATE member SET deleted_at = current_timestamp WHERE id = ?") public class MemberProfile { @Id @@ -43,6 +45,7 @@ public class MemberProfile { @Column(nullable=true, length=255) private Long coordinateX; + @Setter @Column(nullable=true, length=255) private Long coordinateY; @@ -53,4 +56,18 @@ public void prePersist() { public MemberProfile() { } + + public void setAddress( + String defaultAddress, + String addressDetail, + Long coordinateX, + Long coordinateY) { + if (defaultAddress != null) this.defaultAddress = defaultAddress; + if (addressDetail != null) this.addressDetail = addressDetail; + if (coordinateX != null) this.coordinateX = coordinateX; + if (coordinateY != null) this.coordinateY = coordinateY; + + } + + } diff --git a/src/main/java/poomasi/domain/member/controller/MemberController.java b/src/main/java/poomasi/domain/member/controller/MemberController.java index 8d6aa8e4..af7ed1f9 100644 --- a/src/main/java/poomasi/domain/member/controller/MemberController.java +++ b/src/main/java/poomasi/domain/member/controller/MemberController.java @@ -9,6 +9,7 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; import poomasi.domain.auth.security.userdetail.UserDetailsImpl; +import poomasi.domain.member._profile.dto.request.AddressUpdateRequest; import poomasi.domain.member.dto.request.CustomerUpdateRequest; import poomasi.domain.member.dto.request.FarmerUpdateRequest; import poomasi.domain.member.dto.response.*; @@ -99,6 +100,23 @@ public ResponseEntity updateFarmer( return ResponseEntity.ok(memberResponse); } + @PutMapping("/customer/update/address") + @Secured("ROLE_CUSTOMER") + public ResponseEntity updateAddress( + @AuthenticationPrincipal UserDetailsImpl userDetails, + @RequestBody AddressUpdateRequest addressUpdateRequest + ) { + Member member = userDetails.getMember(); + memberService.updateAddress(member, addressUpdateRequest); + return ResponseEntity.ok().build(); + } + + // 배송지 수정 + // 이미지 등록, 수정, 삭제 + // 금지 + // 회원 탈퇴, 복구 + + } diff --git a/src/main/java/poomasi/domain/member/entity/Member.java b/src/main/java/poomasi/domain/member/entity/Member.java index 2517f363..70b60d64 100644 --- a/src/main/java/poomasi/domain/member/entity/Member.java +++ b/src/main/java/poomasi/domain/member/entity/Member.java @@ -77,16 +77,18 @@ public Member(String name, String email, String password, LoginType loginType, R this.password = password; this.loginType = loginType; this.role = role; + this.memberProfile = getOrCreateProfile(); } @Builder - public Member(Long id, String email, String password, Role role, LoginType loginType, String provideId) { + public Member(Long id, String email, String password, Role role, LoginType loginType, String provideId, MemberProfile memberProfile) { this.id = id; this.password = password; this.email = email; this.role = role; this.loginType = loginType; this.provideId = provideId; + this.memberProfile = memberProfile; } public boolean isCustomer() { diff --git a/src/main/java/poomasi/domain/member/service/MemberService.java b/src/main/java/poomasi/domain/member/service/MemberService.java index fe8b9eb2..e7b9a9b0 100644 --- a/src/main/java/poomasi/domain/member/service/MemberService.java +++ b/src/main/java/poomasi/domain/member/service/MemberService.java @@ -7,6 +7,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import poomasi.domain.member._profile.dto.request.AddressUpdateRequest; import poomasi.domain.member._profile.entity.MemberProfile; import poomasi.domain.member.dto.request.CustomerUpdateRequest; import poomasi.domain.member.dto.request.FarmerUpdateRequest; @@ -95,6 +96,7 @@ public Member findMemberById(Long memberId) { .orElseThrow(() -> new BusinessException(MEMBER_NOT_FOUND)); } + @Transactional public Member updateCustomer(Member member, CustomerUpdateRequest customerUpdateRequest) { if (!member.isCustomer()) { @@ -106,6 +108,7 @@ public Member updateCustomer(Member member, CustomerUpdateRequest customerUpdate return memberRepository.save(member); } + @Transactional public Member updateFarmer(Member member, FarmerUpdateRequest farmerUpdateRequest) { if (!member.isFarmer()) { @@ -116,7 +119,9 @@ public Member updateFarmer(Member member, FarmerUpdateRequest farmerUpdateReques MemberProfile profile = member.getOrCreateProfile(); - Optional.ofNullable(farmerUpdateRequest.phoneNumber()).ifPresent(profile::setPhoneNumber); + if (farmerUpdateRequest.phoneNumber() != null) { + profile.setPhoneNumber(farmerUpdateRequest.phoneNumber()); + } Store store = member.getOrCreateStore(); @@ -127,7 +132,6 @@ public Member updateFarmer(Member member, FarmerUpdateRequest farmerUpdateReques store.setAddress(farmerUpdateRequest.storeAddress()); } - return memberRepository.save(member); } @@ -137,4 +141,13 @@ private void updateCommonAttributes(Member member, String name, String email, St if (password != null) member.setPassword(passwordEncoder.encode(password)); } + @Transactional + public void updateAddress(Member member, AddressUpdateRequest request) { + MemberProfile profile = member.getOrCreateProfile(); + + profile.setAddress(request.defaultAddress(), request.addressDetail(), request.coordinateX(), request.coordinateY()); + + memberRepository.save(member); + } + } From 44dedb51d4cc2adb62eeee482313e53701856898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 03:13:37 +0900 Subject: [PATCH 08/26] =?UTF-8?q?refactor:=20customerupdaterequest?= =?UTF-8?q?=EC=97=90=20phonenumber=EB=8F=84=20=EC=B6=94=EA=B0=80=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/_profile/entity/MemberProfile.java | 1 - .../member/controller/MemberController.java | 2 ++ .../dto/request/CustomerUpdateRequest.java | 3 ++- .../domain/member/service/MemberService.java | 17 ++++++++--------- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java b/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java index 5bec6761..b9770da4 100644 --- a/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java +++ b/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java @@ -45,7 +45,6 @@ public class MemberProfile { @Column(nullable=true, length=255) private Long coordinateX; - @Setter @Column(nullable=true, length=255) private Long coordinateY; diff --git a/src/main/java/poomasi/domain/member/controller/MemberController.java b/src/main/java/poomasi/domain/member/controller/MemberController.java index af7ed1f9..b4fa3175 100644 --- a/src/main/java/poomasi/domain/member/controller/MemberController.java +++ b/src/main/java/poomasi/domain/member/controller/MemberController.java @@ -111,6 +111,8 @@ public ResponseEntity updateAddress( return ResponseEntity.ok().build(); } + + // 배송지 수정 // 이미지 등록, 수정, 삭제 // 금지 diff --git a/src/main/java/poomasi/domain/member/dto/request/CustomerUpdateRequest.java b/src/main/java/poomasi/domain/member/dto/request/CustomerUpdateRequest.java index e701460c..693da308 100644 --- a/src/main/java/poomasi/domain/member/dto/request/CustomerUpdateRequest.java +++ b/src/main/java/poomasi/domain/member/dto/request/CustomerUpdateRequest.java @@ -3,5 +3,6 @@ public record CustomerUpdateRequest( String name, String email, - String password) { + String password, + String phoneNumber) { } diff --git a/src/main/java/poomasi/domain/member/service/MemberService.java b/src/main/java/poomasi/domain/member/service/MemberService.java index e7b9a9b0..8d48c257 100644 --- a/src/main/java/poomasi/domain/member/service/MemberService.java +++ b/src/main/java/poomasi/domain/member/service/MemberService.java @@ -103,7 +103,7 @@ public Member updateCustomer(Member member, CustomerUpdateRequest customerUpdate throw new BusinessException(INVALID_ROLE); } - updateCommonAttributes(member, customerUpdateRequest.name(),customerUpdateRequest.email(), customerUpdateRequest.password()); + updateCommonAttributes(member, customerUpdateRequest.name(),customerUpdateRequest.email(), customerUpdateRequest.password(), customerUpdateRequest.phoneNumber()); return memberRepository.save(member); } @@ -115,13 +115,7 @@ public Member updateFarmer(Member member, FarmerUpdateRequest farmerUpdateReques throw new BusinessException(INVALID_ROLE); } - updateCommonAttributes(member, farmerUpdateRequest.name(), farmerUpdateRequest.email(), farmerUpdateRequest.password()); - - MemberProfile profile = member.getOrCreateProfile(); - - if (farmerUpdateRequest.phoneNumber() != null) { - profile.setPhoneNumber(farmerUpdateRequest.phoneNumber()); - } + updateCommonAttributes(member, farmerUpdateRequest.name(), farmerUpdateRequest.email(), farmerUpdateRequest.password(), farmerUpdateRequest.phoneNumber()); Store store = member.getOrCreateStore(); @@ -135,10 +129,15 @@ public Member updateFarmer(Member member, FarmerUpdateRequest farmerUpdateReques return memberRepository.save(member); } - private void updateCommonAttributes(Member member, String name, String email, String password) { + private void updateCommonAttributes(Member member, String name, String email, String password, String phoneNumber) { if (name != null) member.setName(name); if (email != null) member.setEmail(email); if (password != null) member.setPassword(passwordEncoder.encode(password)); + + MemberProfile profile = member.getOrCreateProfile(); + if (phoneNumber != null) { + profile.setPhoneNumber(phoneNumber); + } } @Transactional From 413f6818a5acdcd362c7a24e79a078a935dedd76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:07:43 +0900 Subject: [PATCH 09/26] =?UTF-8?q?fix:=20MemberProfileOwnerValidator=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../validation/MemberProfileOwnerValidator.java | 8 ++++---- .../domain/member/controller/MemberController.java | 13 +++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/main/java/poomasi/domain/image/validation/MemberProfileOwnerValidator.java b/src/main/java/poomasi/domain/image/validation/MemberProfileOwnerValidator.java index b597d5b0..b4836019 100644 --- a/src/main/java/poomasi/domain/image/validation/MemberProfileOwnerValidator.java +++ b/src/main/java/poomasi/domain/image/validation/MemberProfileOwnerValidator.java @@ -2,17 +2,17 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import poomasi.domain.member._profile.repository.MemberProfileRepository; +import poomasi.domain.member.repository.MemberRepository; @Component @RequiredArgsConstructor public class MemberProfileOwnerValidator implements ImageOwnerValidator{ - private final MemberProfileRepository memberProfileRepository; + private final MemberRepository memberRepository; @Override public boolean validateOwner(Long memberId, Long referenceId) { - return memberProfileRepository.findById(referenceId) - .filter(memberProfile -> memberProfile.getMember().getId().equals(memberId)) + return memberRepository.findById(memberId) + .filter(member -> member.getMemberProfile().getId().equals(referenceId)) .isPresent(); } } diff --git a/src/main/java/poomasi/domain/member/controller/MemberController.java b/src/main/java/poomasi/domain/member/controller/MemberController.java index b4fa3175..d5bd974c 100644 --- a/src/main/java/poomasi/domain/member/controller/MemberController.java +++ b/src/main/java/poomasi/domain/member/controller/MemberController.java @@ -111,6 +111,15 @@ public ResponseEntity updateAddress( return ResponseEntity.ok().build(); } + @PostMapping("/profile-image") + @Secured({"ROLE_CUSTOMER", "ROLE_FARMER"}) + public ResponseEntity uploadProfileImage( + @AuthenticationPrincipal UserDetailsImpl userDetails, + @RequestParam("file") MultipartFile file) { + Member member = userDetails.getMember(); + String imageUrl = memberService.uploadProfileImage(member, file); + return ResponseEntity.ok(imageUrl); + } // 배송지 수정 @@ -118,6 +127,10 @@ public ResponseEntity updateAddress( // 금지 // 회원 탈퇴, 복구 + // 이미지 저장 인자 바꾸기 + // 이미지 validator 타입 추가 + + From be42dcbd9c6af916b513a8017425df397e9cb55e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:25:46 +0900 Subject: [PATCH 10/26] =?UTF-8?q?refactor:=20createPresignedPutUrl?= =?UTF-8?q?=EC=97=90=EC=84=9C=20keyname=EB=8F=84=20=EB=B0=98=ED=99=98=20#8?= =?UTF-8?q?2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/poomasi/domain/image/entity/Image.java | 2 +- .../java/poomasi/domain/image/service/ImageService.java | 4 ++-- .../poomasi/global/config/s3/S3PresignedUrlController.java | 3 ++- .../poomasi/global/config/s3/S3PresignedUrlService.java | 7 ++++--- .../config/s3/dto/response/PresignedPutUrlResponse.java | 7 +++++++ 5 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 src/main/java/poomasi/global/config/s3/dto/response/PresignedPutUrlResponse.java diff --git a/src/main/java/poomasi/domain/image/entity/Image.java b/src/main/java/poomasi/domain/image/entity/Image.java index dba3541d..559001f0 100644 --- a/src/main/java/poomasi/domain/image/entity/Image.java +++ b/src/main/java/poomasi/domain/image/entity/Image.java @@ -37,7 +37,7 @@ public class Image { @Column(name = "created_at", nullable = false) @Temporal(TemporalType.TIMESTAMP) - private Date createdAt = new Date(); + private LocalDateTime createdAt = LocalDateTime.now(); @Column(name = "deleted_at") private LocalDateTime deletedAt; diff --git a/src/main/java/poomasi/domain/image/service/ImageService.java b/src/main/java/poomasi/domain/image/service/ImageService.java index cf72c618..8f5695a9 100644 --- a/src/main/java/poomasi/domain/image/service/ImageService.java +++ b/src/main/java/poomasi/domain/image/service/ImageService.java @@ -15,7 +15,7 @@ import poomasi.domain.member.repository.MemberRepository; import poomasi.global.error.BusinessException; -import java.util.Date; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -81,7 +81,7 @@ private Image recoverImageOrThrow(Image existingImage, ImageRequest imageRequest throw new BusinessException(IMAGE_ALREADY_EXISTS); } existingImage.setDeletedAt(null); - existingImage.setCreatedAt(new Date()); + existingImage.setCreatedAt(LocalDateTime.now()); existingImage.update(imageRequest); return existingImage; } diff --git a/src/main/java/poomasi/global/config/s3/S3PresignedUrlController.java b/src/main/java/poomasi/global/config/s3/S3PresignedUrlController.java index 44f5e52b..3b343895 100644 --- a/src/main/java/poomasi/global/config/s3/S3PresignedUrlController.java +++ b/src/main/java/poomasi/global/config/s3/S3PresignedUrlController.java @@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.*; import poomasi.global.config.aws.AwsProperties; import poomasi.global.config.s3.dto.request.PresignedUrlPutRequest; +import poomasi.global.config.s3.dto.response.PresignedPutUrlResponse; @RestController @RequiredArgsConstructor @@ -24,7 +25,7 @@ public ResponseEntity presignedUrlGet(@RequestParam String keyname) { @PostMapping("/presigned-url-put") @Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"}) public ResponseEntity presignedUrlPut(@RequestBody PresignedUrlPutRequest request) { - String presignedPutUrl = s3PresignedUrlService.createPresignedPutUrl(awsProperties.getS3().getBucket(), request.keyPrefix(), request.metadata()); + PresignedPutUrlResponse presignedPutUrl = s3PresignedUrlService.createPresignedPutUrl(awsProperties.getS3().getBucket(), request.keyPrefix(), request.metadata()); return ResponseEntity.ok(presignedPutUrl); } } diff --git a/src/main/java/poomasi/global/config/s3/S3PresignedUrlService.java b/src/main/java/poomasi/global/config/s3/S3PresignedUrlService.java index 241375f3..90d39ece 100644 --- a/src/main/java/poomasi/global/config/s3/S3PresignedUrlService.java +++ b/src/main/java/poomasi/global/config/s3/S3PresignedUrlService.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import poomasi.global.config.s3.dto.response.PresignedPutUrlResponse; import poomasi.global.util.EncryptionUtil; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectRequest; @@ -15,6 +16,7 @@ import java.time.Duration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -46,14 +48,13 @@ public String createPresignedGetUrl(String bucketName, String keyName) { } - public String createPresignedPutUrl(String bucketName, String keyPrefix, Map metadata) { + public PresignedPutUrlResponse createPresignedPutUrl(String bucketName, String keyPrefix, Map metadata) { LocalDateTime now = LocalDateTime.now(); String date = now.format(DATE_FORMATTER); String encodedTime = encryptionUtil.encodeTime(now).substring(0, 10); // jpg 말고 다른 형식 파일 들어오는 경우에 대해서도 따로 처리 필요 // 사진 갯수 5개로 제한하기 - // 극악의 확률로 url이 겹치면?? -> 그럴일 거의 없긴할텐데 생기면 s3 원래 파일 지워짐 String uniqueIdentifier = UUID.randomUUID().toString(); String keyName = String.format("%s/%s/%s_%s.jpg", keyPrefix, date, uniqueIdentifier, encodedTime); @@ -74,7 +75,7 @@ public String createPresignedPutUrl(String bucketName, String keyPrefix, Map Date: Mon, 11 Nov 2024 17:10:31 +0900 Subject: [PATCH 11/26] =?UTF-8?q?refactor:=20createPresignedPutUrl?= =?UTF-8?q?=EC=97=90=EC=84=9C=20objectKey=EB=8F=84=20=EB=B0=98=ED=99=98=20?= =?UTF-8?q?#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/poomasi/domain/image/entity/Image.java | 7 +++---- .../poomasi/domain/member/controller/MemberController.java | 1 + .../poomasi/global/config/s3/S3PresignedUrlController.java | 5 ++++- .../poomasi/global/config/s3/S3PresignedUrlService.java | 7 ++++--- .../config/s3/dto/response/PresignedPutUrlResponse.java | 5 +++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/java/poomasi/domain/image/entity/Image.java b/src/main/java/poomasi/domain/image/entity/Image.java index 559001f0..38d70ebb 100644 --- a/src/main/java/poomasi/domain/image/entity/Image.java +++ b/src/main/java/poomasi/domain/image/entity/Image.java @@ -6,11 +6,10 @@ import poomasi.domain.image.dto.ImageRequest; import java.time.LocalDateTime; -import java.util.Date; @Entity @Table(name = "image", uniqueConstraints = { - @UniqueConstraint(columnNames = {"type", "reference_id", "object_key"}) + @UniqueConstraint(columnNames = {"type", "reference_id"}) }) @Getter @Setter @@ -22,10 +21,10 @@ public class Image { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false) + @Column(nullable = false, unique = true) private String objectKey; - @Column(nullable = false) + @Column(nullable = false, unique = true) private String imageUrl; @Enumerated(EnumType.STRING) diff --git a/src/main/java/poomasi/domain/member/controller/MemberController.java b/src/main/java/poomasi/domain/member/controller/MemberController.java index d5bd974c..09215579 100644 --- a/src/main/java/poomasi/domain/member/controller/MemberController.java +++ b/src/main/java/poomasi/domain/member/controller/MemberController.java @@ -124,6 +124,7 @@ public ResponseEntity uploadProfileImage( // 배송지 수정 // 이미지 등록, 수정, 삭제 + // 농장, 스토어 등 멤버 프로필과 연관 // 금지 // 회원 탈퇴, 복구 diff --git a/src/main/java/poomasi/global/config/s3/S3PresignedUrlController.java b/src/main/java/poomasi/global/config/s3/S3PresignedUrlController.java index 3b343895..46b49f7b 100644 --- a/src/main/java/poomasi/global/config/s3/S3PresignedUrlController.java +++ b/src/main/java/poomasi/global/config/s3/S3PresignedUrlController.java @@ -25,7 +25,10 @@ public ResponseEntity presignedUrlGet(@RequestParam String keyname) { @PostMapping("/presigned-url-put") @Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"}) public ResponseEntity presignedUrlPut(@RequestBody PresignedUrlPutRequest request) { - PresignedPutUrlResponse presignedPutUrl = s3PresignedUrlService.createPresignedPutUrl(awsProperties.getS3().getBucket(), request.keyPrefix(), request.metadata()); + PresignedPutUrlResponse presignedPutUrl = s3PresignedUrlService.createPresignedPutUrl( + awsProperties.getS3().getBucket(), + awsProperties.getS3().getRegion(), + request.keyPrefix(), request.metadata()); return ResponseEntity.ok(presignedPutUrl); } } diff --git a/src/main/java/poomasi/global/config/s3/S3PresignedUrlService.java b/src/main/java/poomasi/global/config/s3/S3PresignedUrlService.java index 90d39ece..b8541f7d 100644 --- a/src/main/java/poomasi/global/config/s3/S3PresignedUrlService.java +++ b/src/main/java/poomasi/global/config/s3/S3PresignedUrlService.java @@ -16,7 +16,6 @@ import java.time.Duration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -48,7 +47,7 @@ public String createPresignedGetUrl(String bucketName, String keyName) { } - public PresignedPutUrlResponse createPresignedPutUrl(String bucketName, String keyPrefix, Map metadata) { + public PresignedPutUrlResponse createPresignedPutUrl(String bucketName, String region, String keyPrefix, Map metadata) { LocalDateTime now = LocalDateTime.now(); String date = now.format(DATE_FORMATTER); String encodedTime = encryptionUtil.encodeTime(now).substring(0, 10); @@ -75,7 +74,9 @@ public PresignedPutUrlResponse createPresignedPutUrl(String bucketName, String k log.info("Presigned URL to upload a file to: [{}]", myURL); log.info("HTTP method: [{}]", presignedRequest.httpRequest().method()); - return new PresignedPutUrlResponse(presignedRequest.url().toExternalForm(), keyName); + String objectUrl = String.format("https://%s.s3.%s.amazonaws.com/%s", bucketName, region, keyName); + + return new PresignedPutUrlResponse(presignedRequest.url().toExternalForm(), keyName, objectUrl); } } diff --git a/src/main/java/poomasi/global/config/s3/dto/response/PresignedPutUrlResponse.java b/src/main/java/poomasi/global/config/s3/dto/response/PresignedPutUrlResponse.java index 76416824..93d48058 100644 --- a/src/main/java/poomasi/global/config/s3/dto/response/PresignedPutUrlResponse.java +++ b/src/main/java/poomasi/global/config/s3/dto/response/PresignedPutUrlResponse.java @@ -1,7 +1,8 @@ package poomasi.global.config.s3.dto.response; public record PresignedPutUrlResponse( - String presignedUrl, - String keyName) { + String presignedPutUrl, + String keyName, + String objectUrl) { } \ No newline at end of file From d616418039a069eea3ee49de7d1baf557556cec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 20:40:05 +0900 Subject: [PATCH 12/26] =?UTF-8?q?feat:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20Lin?= =?UTF-8?q?ker=20=EC=83=9D=EC=84=B1=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/image/linker/ImageLinker.java | 9 ++ .../image/linker/ImageLinkerFactory.java | 26 +++++ .../linker/MemberProfileImageLinker.java | 31 ++++++ .../image/linker/ProductImageLinker.java | 29 ++++++ .../domain/image/service/ImageService.java | 36 +++---- .../FarmOwnerValidator.java | 2 +- .../ImageOwnerValidator.java | 2 +- .../ImageOwnerValidatorFactory.java | 2 +- .../MemberProfileOwnerValidator.java | 2 +- .../ProductOwnerValidator.java | 2 +- .../ReviewOwnerValidator.java | 2 +- .../member/controller/MemberController.java | 16 +-- .../domain/product/entity/Product.java | 2 + .../product/service/ProductService.java | 4 + .../poomasi/global/error/BusinessError.java | 1 + .../config/s3/S3PresignedUrlServiceTest.java | 98 +++++++++---------- 16 files changed, 176 insertions(+), 88 deletions(-) create mode 100644 src/main/java/poomasi/domain/image/linker/ImageLinker.java create mode 100644 src/main/java/poomasi/domain/image/linker/ImageLinkerFactory.java create mode 100644 src/main/java/poomasi/domain/image/linker/MemberProfileImageLinker.java create mode 100644 src/main/java/poomasi/domain/image/linker/ProductImageLinker.java rename src/main/java/poomasi/domain/image/{validation => validator}/FarmOwnerValidator.java (92%) rename src/main/java/poomasi/domain/image/{validation => validator}/ImageOwnerValidator.java (71%) rename src/main/java/poomasi/domain/image/{validation => validator}/ImageOwnerValidatorFactory.java (96%) rename src/main/java/poomasi/domain/image/{validation => validator}/MemberProfileOwnerValidator.java (93%) rename src/main/java/poomasi/domain/image/{validation => validator}/ProductOwnerValidator.java (93%) rename src/main/java/poomasi/domain/image/{validation => validator}/ReviewOwnerValidator.java (93%) diff --git a/src/main/java/poomasi/domain/image/linker/ImageLinker.java b/src/main/java/poomasi/domain/image/linker/ImageLinker.java new file mode 100644 index 00000000..ab0fa128 --- /dev/null +++ b/src/main/java/poomasi/domain/image/linker/ImageLinker.java @@ -0,0 +1,9 @@ +package poomasi.domain.image.linker; + +import poomasi.domain.image.entity.Image; +import poomasi.domain.image.entity.ImageType; + +public interface ImageLinker { + boolean supports(ImageType type); + void link(Long referenceId, Image savedImage); +} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/image/linker/ImageLinkerFactory.java b/src/main/java/poomasi/domain/image/linker/ImageLinkerFactory.java new file mode 100644 index 00000000..0abdfdad --- /dev/null +++ b/src/main/java/poomasi/domain/image/linker/ImageLinkerFactory.java @@ -0,0 +1,26 @@ +package poomasi.domain.image.linker; + +import org.springframework.stereotype.Component; +import poomasi.domain.image.entity.ImageType; +import poomasi.global.error.BusinessException; + +import java.util.List; + +import static poomasi.global.error.BusinessError.IMAGE_TYPE_NOT_FOUND; + +@Component +public class ImageLinkerFactory { + + private final List linkers; + + public ImageLinkerFactory(List linkers) { + this.linkers = linkers; + } + + public ImageLinker getLinker(ImageType type) { + return linkers.stream() + .filter(linker -> linker.supports(type)) + .findFirst() + .orElseThrow(() -> new BusinessException(IMAGE_TYPE_NOT_FOUND)); + } +} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/image/linker/MemberProfileImageLinker.java b/src/main/java/poomasi/domain/image/linker/MemberProfileImageLinker.java new file mode 100644 index 00000000..3008f725 --- /dev/null +++ b/src/main/java/poomasi/domain/image/linker/MemberProfileImageLinker.java @@ -0,0 +1,31 @@ +package poomasi.domain.image.linker; + +import org.springframework.stereotype.Service; +import poomasi.domain.image.entity.Image; +import poomasi.domain.image.entity.ImageType; +import poomasi.domain.member._profile.entity.MemberProfile; +import poomasi.domain.member._profile.service.MemberProfileService; + +@Service +public class MemberProfileImageLinker implements ImageLinker { + + private final MemberProfileService memberProfileService; + + public MemberProfileImageLinker(MemberProfileService memberProfileService) { + this.memberProfileService = memberProfileService; + } + + @Override + public boolean supports(ImageType type) { + return type == ImageType.MEMBER_PROFILE; + } + + @Override + public void link(Long referenceId, Image savedImage) { + MemberProfile memberProfile = memberProfileService.getMemberProfileById(referenceId); + memberProfile.setProfileImage(savedImage); + memberProfileService.saveMemberProfile(memberProfile); + } +} + + diff --git a/src/main/java/poomasi/domain/image/linker/ProductImageLinker.java b/src/main/java/poomasi/domain/image/linker/ProductImageLinker.java new file mode 100644 index 00000000..fc75dac6 --- /dev/null +++ b/src/main/java/poomasi/domain/image/linker/ProductImageLinker.java @@ -0,0 +1,29 @@ +package poomasi.domain.image.linker; + +import org.springframework.stereotype.Service; +import poomasi.domain.image.entity.Image; +import poomasi.domain.image.entity.ImageType; +import poomasi.domain.product.entity.Product; +import poomasi.domain.product.service.ProductService; + +@Service +public class ProductImageLinker implements ImageLinker { + + private final ProductService productService; + + public ProductImageLinker(ProductService productService) { + this.productService = productService; + } + + @Override + public boolean supports(ImageType type) { + return type == ImageType.PRODUCT; + } + + @Override + public void link(Long referenceId, Image savedImage) { + Product product = productService.findProductById(referenceId); + product.setImageUrl(savedImage.getImageUrl()); + productService.saveExistedProduct(product); + } +} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/image/service/ImageService.java b/src/main/java/poomasi/domain/image/service/ImageService.java index 8f5695a9..98199313 100644 --- a/src/main/java/poomasi/domain/image/service/ImageService.java +++ b/src/main/java/poomasi/domain/image/service/ImageService.java @@ -6,13 +6,13 @@ import poomasi.domain.image.dto.ImageRequest; import poomasi.domain.image.entity.Image; import poomasi.domain.image.entity.ImageType; +import poomasi.domain.image.linker.ImageLinker; +import poomasi.domain.image.linker.ImageLinkerFactory; import poomasi.domain.image.repository.ImageRepository; -import poomasi.domain.image.validation.ImageOwnerValidator; -import poomasi.domain.image.validation.ImageOwnerValidatorFactory; -import poomasi.domain.member._profile.entity.MemberProfile; -import poomasi.domain.member._profile.service.MemberProfileService; +import poomasi.domain.image.validator.ImageOwnerValidator; +import poomasi.domain.image.validator.ImageOwnerValidatorFactory; import poomasi.domain.member.entity.Member; -import poomasi.domain.member.repository.MemberRepository; +import poomasi.domain.member.service.MemberService; import poomasi.global.error.BusinessException; import java.time.LocalDateTime; @@ -28,12 +28,12 @@ public class ImageService { private static final int DEFAULT_IMAGE_LIMIT = 5; - private static final int MEMBER_PROFILE_IMAGE_LIMIT = 1; + private static final int IMAGE_ONE_LIMIT = 1; private final ImageRepository imageRepository; private final ImageOwnerValidatorFactory validatorFactory; - private final MemberRepository memberRepository; - private final MemberProfileService memberProfileService; + private final MemberService memberService; + private final ImageLinkerFactory imageLinkerFactory; @Transactional @@ -46,9 +46,8 @@ public Image saveImage(Long memberId, ImageRequest imageRequest) { .map(existingImage -> recoverImageOrThrow(existingImage, imageRequest)) .orElseGet(() -> imageRequest.toEntity(imageRequest)); - if (imageRequest.type() == ImageType.MEMBER_PROFILE) { - linkImageToMemberProfile(imageRequest.referenceId(), image); - } + ImageLinker linker = imageLinkerFactory.getLinker(imageRequest.type()); + linker.link(imageRequest.referenceId(), image); return imageRepository.save(image); } @@ -66,8 +65,7 @@ private void validateImageOwner(Long memberId, ImageType type, Long referenceId) } private boolean isAdmin(Long memberId) { - Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new BusinessException(MEMBER_NOT_FOUND)); + Member member = memberService.findMemberById(memberId); return member.isAdmin(); } @@ -88,8 +86,8 @@ private Image recoverImageOrThrow(Image existingImage, ImageRequest imageRequest private void validateImageLimit(ImageRequest imageRequest) { int imageLimit = DEFAULT_IMAGE_LIMIT; - if (imageRequest.type() == ImageType.MEMBER_PROFILE) { - imageLimit = MEMBER_PROFILE_IMAGE_LIMIT; // 멤버 프로필 이미지는 한 장으로 제한 + if (imageRequest.type() == ImageType.MEMBER_PROFILE || imageRequest.type() == ImageType.PRODUCT) { + imageLimit = IMAGE_ONE_LIMIT; // 멤버 프로필 이미지는 한 장으로 제한 } if (imageRepository.countByTypeAndReferenceIdAndDeletedAtIsNull(imageRequest.type(), imageRequest.referenceId()) >= imageLimit) { @@ -97,12 +95,6 @@ private void validateImageLimit(ImageRequest imageRequest) { } } - private void linkImageToMemberProfile(Long referenceId, Image savedImage) { - MemberProfile memberProfile = memberProfileService.getMemberProfileById(referenceId); - memberProfile.setProfileImage(savedImage); - memberProfileService.saveMemberProfile(memberProfile); - } - // 여러 이미지 저장 @Transactional public List saveMultipleImages(Long memberId, List imageRequests) { @@ -115,7 +107,7 @@ public List saveMultipleImages(Long memberId, List imageReq public void deleteImage(Long memberId, Long id) { Image image = getImageById(id); validateImageOwner(memberId, image.getType(), image.getReferenceId()); - imageRepository.deleteById(id); + imageRepository.delete(image); } public Image getImageById(Long id) { diff --git a/src/main/java/poomasi/domain/image/validation/FarmOwnerValidator.java b/src/main/java/poomasi/domain/image/validator/FarmOwnerValidator.java similarity index 92% rename from src/main/java/poomasi/domain/image/validation/FarmOwnerValidator.java rename to src/main/java/poomasi/domain/image/validator/FarmOwnerValidator.java index ca376272..193aa1a0 100644 --- a/src/main/java/poomasi/domain/image/validation/FarmOwnerValidator.java +++ b/src/main/java/poomasi/domain/image/validator/FarmOwnerValidator.java @@ -1,4 +1,4 @@ -package poomasi.domain.image.validation; +package poomasi.domain.image.validator; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; diff --git a/src/main/java/poomasi/domain/image/validation/ImageOwnerValidator.java b/src/main/java/poomasi/domain/image/validator/ImageOwnerValidator.java similarity index 71% rename from src/main/java/poomasi/domain/image/validation/ImageOwnerValidator.java rename to src/main/java/poomasi/domain/image/validator/ImageOwnerValidator.java index 8b51556f..1faa853f 100644 --- a/src/main/java/poomasi/domain/image/validation/ImageOwnerValidator.java +++ b/src/main/java/poomasi/domain/image/validator/ImageOwnerValidator.java @@ -1,4 +1,4 @@ -package poomasi.domain.image.validation; +package poomasi.domain.image.validator; public interface ImageOwnerValidator { boolean validateOwner(Long memberId, Long referenceId); diff --git a/src/main/java/poomasi/domain/image/validation/ImageOwnerValidatorFactory.java b/src/main/java/poomasi/domain/image/validator/ImageOwnerValidatorFactory.java similarity index 96% rename from src/main/java/poomasi/domain/image/validation/ImageOwnerValidatorFactory.java rename to src/main/java/poomasi/domain/image/validator/ImageOwnerValidatorFactory.java index d22141b2..2de7c789 100644 --- a/src/main/java/poomasi/domain/image/validation/ImageOwnerValidatorFactory.java +++ b/src/main/java/poomasi/domain/image/validator/ImageOwnerValidatorFactory.java @@ -1,4 +1,4 @@ -package poomasi.domain.image.validation; +package poomasi.domain.image.validator; import org.springframework.stereotype.Component; import poomasi.domain.image.entity.ImageType; diff --git a/src/main/java/poomasi/domain/image/validation/MemberProfileOwnerValidator.java b/src/main/java/poomasi/domain/image/validator/MemberProfileOwnerValidator.java similarity index 93% rename from src/main/java/poomasi/domain/image/validation/MemberProfileOwnerValidator.java rename to src/main/java/poomasi/domain/image/validator/MemberProfileOwnerValidator.java index b4836019..f49c12ea 100644 --- a/src/main/java/poomasi/domain/image/validation/MemberProfileOwnerValidator.java +++ b/src/main/java/poomasi/domain/image/validator/MemberProfileOwnerValidator.java @@ -1,4 +1,4 @@ -package poomasi.domain.image.validation; +package poomasi.domain.image.validator; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; diff --git a/src/main/java/poomasi/domain/image/validation/ProductOwnerValidator.java b/src/main/java/poomasi/domain/image/validator/ProductOwnerValidator.java similarity index 93% rename from src/main/java/poomasi/domain/image/validation/ProductOwnerValidator.java rename to src/main/java/poomasi/domain/image/validator/ProductOwnerValidator.java index 6afc0bfb..43175fa2 100644 --- a/src/main/java/poomasi/domain/image/validation/ProductOwnerValidator.java +++ b/src/main/java/poomasi/domain/image/validator/ProductOwnerValidator.java @@ -1,4 +1,4 @@ -package poomasi.domain.image.validation; +package poomasi.domain.image.validator; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; diff --git a/src/main/java/poomasi/domain/image/validation/ReviewOwnerValidator.java b/src/main/java/poomasi/domain/image/validator/ReviewOwnerValidator.java similarity index 93% rename from src/main/java/poomasi/domain/image/validation/ReviewOwnerValidator.java rename to src/main/java/poomasi/domain/image/validator/ReviewOwnerValidator.java index 57073e2d..5f8d8d6b 100644 --- a/src/main/java/poomasi/domain/image/validation/ReviewOwnerValidator.java +++ b/src/main/java/poomasi/domain/image/validator/ReviewOwnerValidator.java @@ -1,4 +1,4 @@ -package poomasi.domain.image.validation; +package poomasi.domain.image.validator; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; diff --git a/src/main/java/poomasi/domain/member/controller/MemberController.java b/src/main/java/poomasi/domain/member/controller/MemberController.java index 09215579..591ee00a 100644 --- a/src/main/java/poomasi/domain/member/controller/MemberController.java +++ b/src/main/java/poomasi/domain/member/controller/MemberController.java @@ -111,27 +111,21 @@ public ResponseEntity updateAddress( return ResponseEntity.ok().build(); } - @PostMapping("/profile-image") - @Secured({"ROLE_CUSTOMER", "ROLE_FARMER"}) - public ResponseEntity uploadProfileImage( - @AuthenticationPrincipal UserDetailsImpl userDetails, - @RequestParam("file") MultipartFile file) { - Member member = userDetails.getMember(); - String imageUrl = memberService.uploadProfileImage(member, file); - return ResponseEntity.ok(imageUrl); - } - - // 배송지 수정 // 이미지 등록, 수정, 삭제 // 농장, 스토어 등 멤버 프로필과 연관 // 금지 // 회원 탈퇴, 복구 + // s3스케줄러 구현하긴해야함 // 이미지 저장 인자 바꾸기 // 이미지 validator 타입 추가 + // 이미지 저장 엔티티마다 만들어야 하나 -> 하나에서 처리하자 그냥 + // 이미지 업로드 실패할시 + + diff --git a/src/main/java/poomasi/domain/product/entity/Product.java b/src/main/java/poomasi/domain/product/entity/Product.java index 8c70ba51..14ecdfcf 100644 --- a/src/main/java/poomasi/domain/product/entity/Product.java +++ b/src/main/java/poomasi/domain/product/entity/Product.java @@ -20,6 +20,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import org.hibernate.annotations.Comment; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; @@ -50,6 +51,7 @@ public class Product { @Comment("상품 설명") private String description; + @Setter @Comment("이미지 URL") private String imageUrl; diff --git a/src/main/java/poomasi/domain/product/service/ProductService.java b/src/main/java/poomasi/domain/product/service/ProductService.java index 79b73dca..f2b75ce1 100644 --- a/src/main/java/poomasi/domain/product/service/ProductService.java +++ b/src/main/java/poomasi/domain/product/service/ProductService.java @@ -39,4 +39,8 @@ public Product findProductById(Long productId) { return productRepository.findByIdAndDeletedAtIsNull(productId) .orElseThrow(() -> new BusinessException(BusinessError.PRODUCT_NOT_FOUND)); } + + public void saveExistedProduct(Product product) { + productRepository.save(product); + } } diff --git a/src/main/java/poomasi/global/error/BusinessError.java b/src/main/java/poomasi/global/error/BusinessError.java index b4bd8a56..128b3511 100644 --- a/src/main/java/poomasi/global/error/BusinessError.java +++ b/src/main/java/poomasi/global/error/BusinessError.java @@ -72,6 +72,7 @@ public enum BusinessError { IMAGE_ALREADY_EXISTS(HttpStatus.CONFLICT, "이미 이미지가 존재합니다"), IMAGE_NOT_FOUND(HttpStatus.NOT_FOUND, "이미지를 찾을 수 없습니다."), IMAGE_OWNER_MISMATCH(HttpStatus.FORBIDDEN, "해당 이미지의 소유자가 아닙니다."), + IMAGE_TYPE_NOT_FOUND(HttpStatus.NOT_FOUND, "지원하지 않는 이미지 타입입니다."), // Order ORDER_NOT_FOUND(HttpStatus.NOT_FOUND, "주문을 찾을 수 없습니다."), diff --git a/src/test/java/poomasi/global/config/s3/S3PresignedUrlServiceTest.java b/src/test/java/poomasi/global/config/s3/S3PresignedUrlServiceTest.java index 7bf948ae..2a11f880 100644 --- a/src/test/java/poomasi/global/config/s3/S3PresignedUrlServiceTest.java +++ b/src/test/java/poomasi/global/config/s3/S3PresignedUrlServiceTest.java @@ -24,53 +24,53 @@ public class S3PresignedUrlServiceTest { @Autowired private AwsProperties awsProperties; - @BeforeEach - public void setUp() { - String accessKey = awsProperties.getAccess(); - String secretKey = awsProperties.getSecret(); - String region = awsProperties.getS3().getRegion(); - - // 자격 증명 설정 - AwsBasicCredentials awsCreds = AwsBasicCredentials.create( - accessKey, - secretKey - ); - - // S3Presigner 인스턴스 생성 - S3Presigner presigner = S3Presigner.builder() - .credentialsProvider(StaticCredentialsProvider.create(awsCreds)) - .region(Region.of(region)) - .build(); - - // S3PresignedUrlService 초기화 - s3PresignedUrlService = new S3PresignedUrlService(presigner, new EncryptionUtil()); - } - - @Test - public void testCreatePresignedGetUrl() { - String objectKey = "object_key"; - String bucketName = awsProperties.getS3().getBucket(); - - String presignedUrl = s3PresignedUrlService.createPresignedGetUrl(bucketName, objectKey); - - assertNotNull(presignedUrl); - System.out.println("Presigned GET URL: " + presignedUrl); - } - - @Test - public void testCreatePresignedPutUrl() { - String keyPrefix = "uploads"; - String bucketName = awsProperties.getS3().getBucket(); - - // 메타데이터 생성 - Map metadata = new HashMap<>(); - metadata.put("Content-Type", "image/jpg"); - metadata.put("x-amz-meta-title", "Test Image"); - - // presigned PUT URL 생성 - String presignedUrl = s3PresignedUrlService.createPresignedPutUrl(bucketName, keyPrefix, metadata); - - assertNotNull(presignedUrl); - System.out.println("Presigned PUT URL: " + presignedUrl); - } +// @BeforeEach +// public void setUp() { +// String accessKey = awsProperties.getAccess(); +// String secretKey = awsProperties.getSecret(); +// String region = awsProperties.getS3().getRegion(); +// +// // 자격 증명 설정 +// AwsBasicCredentials awsCreds = AwsBasicCredentials.create( +// accessKey, +// secretKey +// ); +// +// // S3Presigner 인스턴스 생성 +// S3Presigner presigner = S3Presigner.builder() +// .credentialsProvider(StaticCredentialsProvider.create(awsCreds)) +// .region(Region.of(region)) +// .build(); +// +// // S3PresignedUrlService 초기화 +// s3PresignedUrlService = new S3PresignedUrlService(presigner, new EncryptionUtil()); +// } +// +// @Test +// public void testCreatePresignedGetUrl() { +// String objectKey = "object_key"; +// String bucketName = awsProperties.getS3().getBucket(); +// +// String presignedUrl = s3PresignedUrlService.createPresignedGetUrl(bucketName, objectKey); +// +// assertNotNull(presignedUrl); +// System.out.println("Presigned GET URL: " + presignedUrl); +// } +// +// @Test +// public void testCreatePresignedPutUrl() { +// String keyPrefix = "uploads"; +// String bucketName = awsProperties.getS3().getBucket(); +// +// // 메타데이터 생성 +// Map metadata = new HashMap<>(); +// metadata.put("Content-Type", "image/jpg"); +// metadata.put("x-amz-meta-title", "Test Image"); +// +// // presigned PUT URL 생성 +// String presignedUrl = s3PresignedUrlService.createPresignedPutUrl(bucketName, keyPrefix, metadata); +// +// assertNotNull(presignedUrl); +// System.out.println("Presigned PUT URL: " + presignedUrl); +// } } From 77386d768dd9539988d01c17783d6d067f301eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 21:35:56 +0900 Subject: [PATCH 13/26] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20DeleteLinker=20=EC=83=9D=EC=84=B1=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deleteLinker/ImageDeleteFactory.java | 25 +++++++++++ .../image/deleteLinker/ImageDeleteLinker.java | 7 ++++ .../MemberProfileDeleteLinker.java | 24 +++++++++++ .../deleteLinker/ProductDeleteLinker.java | 23 ++++++++++ .../image/linker/ImageLinkerFactory.java | 5 +-- .../domain/image/service/ImageService.java | 42 +++++++++++++++++-- .../domain/product/entity/Product.java | 24 +++++------ .../poomasi/global/error/BusinessError.java | 1 - 8 files changed, 128 insertions(+), 23 deletions(-) create mode 100644 src/main/java/poomasi/domain/image/deleteLinker/ImageDeleteFactory.java create mode 100644 src/main/java/poomasi/domain/image/deleteLinker/ImageDeleteLinker.java create mode 100644 src/main/java/poomasi/domain/image/deleteLinker/MemberProfileDeleteLinker.java create mode 100644 src/main/java/poomasi/domain/image/deleteLinker/ProductDeleteLinker.java diff --git a/src/main/java/poomasi/domain/image/deleteLinker/ImageDeleteFactory.java b/src/main/java/poomasi/domain/image/deleteLinker/ImageDeleteFactory.java new file mode 100644 index 00000000..821b7353 --- /dev/null +++ b/src/main/java/poomasi/domain/image/deleteLinker/ImageDeleteFactory.java @@ -0,0 +1,25 @@ +package poomasi.domain.image.deleteLinker; + +import org.springframework.stereotype.Component; +import poomasi.domain.image.entity.ImageType; + +import java.util.HashMap; +import java.util.Map; + +@Component +public class ImageDeleteFactory { + + private final Map handlerMap; + + public ImageDeleteFactory( + ProductDeleteLinker productDeleteLinker, + MemberProfileDeleteLinker memberProfileDeleteLinker) { + this.handlerMap = new HashMap<>(); + handlerMap.put(ImageType.PRODUCT, productDeleteLinker); + handlerMap.put(ImageType.MEMBER_PROFILE, memberProfileDeleteLinker); + } + + public ImageDeleteLinker getDeleteLinker(ImageType type) { + return handlerMap.get(type); + } +} diff --git a/src/main/java/poomasi/domain/image/deleteLinker/ImageDeleteLinker.java b/src/main/java/poomasi/domain/image/deleteLinker/ImageDeleteLinker.java new file mode 100644 index 00000000..c5820c90 --- /dev/null +++ b/src/main/java/poomasi/domain/image/deleteLinker/ImageDeleteLinker.java @@ -0,0 +1,7 @@ +package poomasi.domain.image.deleteLinker; + +import poomasi.domain.image.entity.Image; + +public interface ImageDeleteLinker { + void handleImageDeletion(Image image); +} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/image/deleteLinker/MemberProfileDeleteLinker.java b/src/main/java/poomasi/domain/image/deleteLinker/MemberProfileDeleteLinker.java new file mode 100644 index 00000000..696bed0d --- /dev/null +++ b/src/main/java/poomasi/domain/image/deleteLinker/MemberProfileDeleteLinker.java @@ -0,0 +1,24 @@ +package poomasi.domain.image.deleteLinker; + +import org.springframework.stereotype.Component; +import poomasi.domain.image.entity.Image; +import poomasi.domain.member._profile.entity.MemberProfile; +import poomasi.domain.member._profile.service.MemberProfileService; + +@Component +public class MemberProfileDeleteLinker implements ImageDeleteLinker { + + private final MemberProfileService memberProfileService; + + public MemberProfileDeleteLinker(MemberProfileService memberProfileService) { + this.memberProfileService = memberProfileService; + } + + @Override + public void handleImageDeletion(Image image) { + MemberProfile memberProfile = memberProfileService.getMemberProfileById(image.getReferenceId()); + memberProfile.setProfileImage(null); + memberProfileService.saveMemberProfile(memberProfile); + } +} + diff --git a/src/main/java/poomasi/domain/image/deleteLinker/ProductDeleteLinker.java b/src/main/java/poomasi/domain/image/deleteLinker/ProductDeleteLinker.java new file mode 100644 index 00000000..9453cbce --- /dev/null +++ b/src/main/java/poomasi/domain/image/deleteLinker/ProductDeleteLinker.java @@ -0,0 +1,23 @@ +package poomasi.domain.image.deleteLinker; + +import org.springframework.stereotype.Component; +import poomasi.domain.image.entity.Image; +import poomasi.domain.product.entity.Product; +import poomasi.domain.product.service.ProductService; + +@Component +public class ProductDeleteLinker implements ImageDeleteLinker { + + private final ProductService productService; + + public ProductDeleteLinker(ProductService productService) { + this.productService = productService; + } + + @Override + public void handleImageDeletion(Image image) { + Product product = productService.findProductById(image.getReferenceId()); + product.setImageUrl(null); + productService.saveExistedProduct(product); + } +} diff --git a/src/main/java/poomasi/domain/image/linker/ImageLinkerFactory.java b/src/main/java/poomasi/domain/image/linker/ImageLinkerFactory.java index 0abdfdad..1064266e 100644 --- a/src/main/java/poomasi/domain/image/linker/ImageLinkerFactory.java +++ b/src/main/java/poomasi/domain/image/linker/ImageLinkerFactory.java @@ -2,12 +2,9 @@ import org.springframework.stereotype.Component; import poomasi.domain.image.entity.ImageType; -import poomasi.global.error.BusinessException; import java.util.List; -import static poomasi.global.error.BusinessError.IMAGE_TYPE_NOT_FOUND; - @Component public class ImageLinkerFactory { @@ -21,6 +18,6 @@ public ImageLinker getLinker(ImageType type) { return linkers.stream() .filter(linker -> linker.supports(type)) .findFirst() - .orElseThrow(() -> new BusinessException(IMAGE_TYPE_NOT_FOUND)); + .orElse(null); } } \ No newline at end of file diff --git a/src/main/java/poomasi/domain/image/service/ImageService.java b/src/main/java/poomasi/domain/image/service/ImageService.java index 98199313..b0cabc50 100644 --- a/src/main/java/poomasi/domain/image/service/ImageService.java +++ b/src/main/java/poomasi/domain/image/service/ImageService.java @@ -3,6 +3,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import poomasi.domain.image.deleteLinker.ImageDeleteFactory; +import poomasi.domain.image.deleteLinker.ImageDeleteLinker; import poomasi.domain.image.dto.ImageRequest; import poomasi.domain.image.entity.Image; import poomasi.domain.image.entity.ImageType; @@ -31,10 +33,12 @@ public class ImageService { private static final int IMAGE_ONE_LIMIT = 1; private final ImageRepository imageRepository; - private final ImageOwnerValidatorFactory validatorFactory; private final MemberService memberService; + private final ImageOwnerValidatorFactory validatorFactory; private final ImageLinkerFactory imageLinkerFactory; + private final ImageDeleteFactory imageDeleteFactory; + // 이미지 타입에 맞게 link, deleteLink, 개수 제한, ownerValidate @Transactional public Image saveImage(Long memberId, ImageRequest imageRequest) { @@ -46,8 +50,7 @@ public Image saveImage(Long memberId, ImageRequest imageRequest) { .map(existingImage -> recoverImageOrThrow(existingImage, imageRequest)) .orElseGet(() -> imageRequest.toEntity(imageRequest)); - ImageLinker linker = imageLinkerFactory.getLinker(imageRequest.type()); - linker.link(imageRequest.referenceId(), image); + imageLink(image); return imageRepository.save(image); } @@ -87,7 +90,7 @@ private Image recoverImageOrThrow(Image existingImage, ImageRequest imageRequest private void validateImageLimit(ImageRequest imageRequest) { int imageLimit = DEFAULT_IMAGE_LIMIT; if (imageRequest.type() == ImageType.MEMBER_PROFILE || imageRequest.type() == ImageType.PRODUCT) { - imageLimit = IMAGE_ONE_LIMIT; // 멤버 프로필 이미지는 한 장으로 제한 + imageLimit = IMAGE_ONE_LIMIT; // 멤버 프로필, 상품 이미지는 한 장으로 제한 } if (imageRepository.countByTypeAndReferenceIdAndDeletedAtIsNull(imageRequest.type(), imageRequest.referenceId()) >= imageLimit) { @@ -108,6 +111,8 @@ public void deleteImage(Long memberId, Long id) { Image image = getImageById(id); validateImageOwner(memberId, image.getType(), image.getReferenceId()); imageRepository.delete(image); + + imageDeleteLink(image); } public Image getImageById(Long id) { @@ -130,8 +135,17 @@ public Image updateImage(Long memberId, Long id, ImageRequest imageRequest) { validateImageLimit(imageRequest); } + if (!image.getType().equals(imageRequest.type())) { + imageDeleteLink(image); + } + image.update(imageRequest); + if (!image.getType().equals(imageRequest.type())) { + imageLink(image); + } + + return imageRepository.save(image); } @@ -147,7 +161,27 @@ public void recoverImage(Long memberId, Long id) { validateImageLimit(image.toRequest(image)); image.setDeletedAt(null); + + imageLink(image); + imageRepository.save(image); } + // 이미지와 해당 이미지를 가지는 엔티티 연결 + private void imageLink(Image image){ + ImageLinker linker = imageLinkerFactory.getLinker(image.getType()); + if (linker != null){ + linker.link(image.getReferenceId(), image); + } + } + + // 이미지 삭제 시 해당 이미지를 가지는 엔티티에서도 처리 + private void imageDeleteLink(Image image){ + ImageDeleteLinker imageDeleteLinker = imageDeleteFactory.getDeleteLinker(image.getType()); + if (imageDeleteLinker != null) { + imageDeleteLinker.handleImageDeletion(image); // 해당 타입에 맞는 삭제 처리 + } + } + + } \ No newline at end of file diff --git a/src/main/java/poomasi/domain/product/entity/Product.java b/src/main/java/poomasi/domain/product/entity/Product.java index 14ecdfcf..875189d8 100644 --- a/src/main/java/poomasi/domain/product/entity/Product.java +++ b/src/main/java/poomasi/domain/product/entity/Product.java @@ -1,19 +1,7 @@ package poomasi.domain.product.entity; -import jakarta.persistence.CascadeType; -import jakarta.persistence.CollectionTable; -import jakarta.persistence.Column; -import jakarta.persistence.ElementCollection; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; +import jakarta.persistence.*; + import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -24,6 +12,7 @@ import org.hibernate.annotations.Comment; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; +import poomasi.domain.image.entity.Image; import poomasi.domain.order.entity.OrderProductDetails; import poomasi.domain.store.entity.Store; import poomasi.domain.product.dto.ProductRegisterRequest; @@ -91,6 +80,13 @@ public class Product { @JoinColumn(name = "order_product_details_id") private List orderProductDetails; +// @PreRemove +// public void preRemove() { +// // Product가 삭제되기 전에 연관된 이미지를 삭제 +// for (Image image : images) { +// image.setDeletedAt(LocalDateTime.now()); +// } +// } @Builder public Product(Long productId, diff --git a/src/main/java/poomasi/global/error/BusinessError.java b/src/main/java/poomasi/global/error/BusinessError.java index 128b3511..b4bd8a56 100644 --- a/src/main/java/poomasi/global/error/BusinessError.java +++ b/src/main/java/poomasi/global/error/BusinessError.java @@ -72,7 +72,6 @@ public enum BusinessError { IMAGE_ALREADY_EXISTS(HttpStatus.CONFLICT, "이미 이미지가 존재합니다"), IMAGE_NOT_FOUND(HttpStatus.NOT_FOUND, "이미지를 찾을 수 없습니다."), IMAGE_OWNER_MISMATCH(HttpStatus.FORBIDDEN, "해당 이미지의 소유자가 아닙니다."), - IMAGE_TYPE_NOT_FOUND(HttpStatus.NOT_FOUND, "지원하지 않는 이미지 타입입니다."), // Order ORDER_NOT_FOUND(HttpStatus.NOT_FOUND, "주문을 찾을 수 없습니다."), From 7ced941aeb6c52b7c6de00eecbf78d2d2bf74bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:33:05 +0900 Subject: [PATCH 14/26] =?UTF-8?q?feat:=20=EB=86=8D=EB=B6=80=20=EB=B3=84=20?= =?UTF-8?q?=EB=86=8D=EC=9E=A5=20=EC=A1=B0=ED=9A=8C=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/farm/controller/FarmController.java | 5 +++++ .../domain/farm/service/FarmPlatformService.java | 6 ++++++ .../member/_profile/entity/MemberProfile.java | 14 +++++++++++++- .../domain/member/controller/MemberController.java | 11 ++--------- .../java/poomasi/domain/member/entity/Member.java | 2 +- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/main/java/poomasi/domain/farm/controller/FarmController.java b/src/main/java/poomasi/domain/farm/controller/FarmController.java index cb3c81af..f1763f5f 100644 --- a/src/main/java/poomasi/domain/farm/controller/FarmController.java +++ b/src/main/java/poomasi/domain/farm/controller/FarmController.java @@ -25,4 +25,9 @@ public ResponseEntity getFarm(@PathVariable Long farmId) { public ResponseEntity getFarmList(Pageable pageable) { return ResponseEntity.ok(farmPlatformService.getFarmList(pageable)); } + + @GetMapping("byFarmer/{farmerId}") + public ResponseEntity getFarmsByFarmerId(@PathVariable Long farmerId) { + return ResponseEntity.ok(farmPlatformService.getFarmsByFarmerId(farmerId)); + } } diff --git a/src/main/java/poomasi/domain/farm/service/FarmPlatformService.java b/src/main/java/poomasi/domain/farm/service/FarmPlatformService.java index 54032ecf..2ace44df 100644 --- a/src/main/java/poomasi/domain/farm/service/FarmPlatformService.java +++ b/src/main/java/poomasi/domain/farm/service/FarmPlatformService.java @@ -22,4 +22,10 @@ public List getFarmList(Pageable pageable) { .map(FarmResponse::fromEntity) .collect(Collectors.toList()); } + + public List getFarmsByFarmerId(Long farmerId) { + return farmService.getFarmListByOwnerId(farmerId).stream() + .map(FarmResponse::fromEntity) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java b/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java index b9770da4..05a969c1 100644 --- a/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java +++ b/src/main/java/poomasi/domain/member/_profile/entity/MemberProfile.java @@ -12,7 +12,7 @@ @Table(name = "member_profile") @AllArgsConstructor @Builder -@SQLDelete(sql = "UPDATE member SET deleted_at = current_timestamp WHERE id = ?") +@SQLDelete(sql = "UPDATE member_profile SET deleted_at = current_timestamp WHERE id = ?") public class MemberProfile { @Id @@ -30,6 +30,10 @@ public class MemberProfile { @Column(nullable = false) private LocalDateTime createdAt; + @Setter + @Column + private LocalDateTime deletedAt; + @Setter @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "profile_image_id") @@ -53,6 +57,14 @@ public void prePersist() { this.createdAt = LocalDateTime.now(); } + @PreRemove + public void preRemove() { + // MemberProfile이 삭제되기 전에 연관된 이미지를 삭제 + if (profileImage != null) { + profileImage.setDeletedAt(LocalDateTime.now()); + } + } + public MemberProfile() { } diff --git a/src/main/java/poomasi/domain/member/controller/MemberController.java b/src/main/java/poomasi/domain/member/controller/MemberController.java index 591ee00a..19de271e 100644 --- a/src/main/java/poomasi/domain/member/controller/MemberController.java +++ b/src/main/java/poomasi/domain/member/controller/MemberController.java @@ -111,19 +111,12 @@ public ResponseEntity updateAddress( return ResponseEntity.ok().build(); } - // 배송지 수정 - // 이미지 등록, 수정, 삭제 - // 농장, 스토어 등 멤버 프로필과 연관 - // 금지 - // 회원 탈퇴, 복구 + // 회원 탈퇴, 복구, 금지 // s3스케줄러 구현하긴해야함 - // 이미지 저장 인자 바꾸기 // 이미지 validator 타입 추가 - - // 이미지 저장 엔티티마다 만들어야 하나 -> 하나에서 처리하자 그냥 - // 이미지 업로드 실패할시 + // 이미지 업로드 실패할시 처리 diff --git a/src/main/java/poomasi/domain/member/entity/Member.java b/src/main/java/poomasi/domain/member/entity/Member.java index 70b60d64..e4b75fd9 100644 --- a/src/main/java/poomasi/domain/member/entity/Member.java +++ b/src/main/java/poomasi/domain/member/entity/Member.java @@ -51,7 +51,7 @@ public class Member { @Column(nullable = true) private String provideId; - @OneToOne(mappedBy = "member", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @OneToOne(mappedBy = "member", fetch = FetchType.LAZY) private MemberProfile memberProfile; @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, fetch = FetchType.LAZY) From d2f8c923f84d4412dc31ededae50673c457d37b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:44:24 +0900 Subject: [PATCH 15/26] =?UTF-8?q?fix:=20=EB=A9=A4=EB=B2=84<->=EB=A9=A4?= =?UTF-8?q?=EB=B2=84=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/poomasi/domain/member/entity/Member.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/poomasi/domain/member/entity/Member.java b/src/main/java/poomasi/domain/member/entity/Member.java index e4b75fd9..6a3e08d6 100644 --- a/src/main/java/poomasi/domain/member/entity/Member.java +++ b/src/main/java/poomasi/domain/member/entity/Member.java @@ -51,7 +51,7 @@ public class Member { @Column(nullable = true) private String provideId; - @OneToOne(mappedBy = "member", fetch = FetchType.LAZY) + @OneToOne(fetch = FetchType.LAZY) private MemberProfile memberProfile; @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, fetch = FetchType.LAZY) @@ -127,4 +127,3 @@ public Store getOrCreateStore() { } -//멤버에 농장, 스토어 두고 거기서 주솟값 가져오는 걸로 바꾸기 \ No newline at end of file From 293e88e9b215c092332aa2e6ddaf245e2e613d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=80=EB=AF=BC?= <108014449+stopmin@users.noreply.github.com> Date: Tue, 12 Nov 2024 13:17:02 +0900 Subject: [PATCH 16/26] =?UTF-8?q?[TEST]=20FarmSchedule=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1=20(#1?= =?UTF-8?q?50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: FarmScheduleServiceTest - 농장 스케쥴 추가 #125 * test: FarmScheduleServiceTest - 농장 스케쥴 추가 #113 * test: FarmScheduleServiceTest - 농장 스케쥴 추가 #113 * test: FarmScheduleServiceTest - 농장이 존재하지 않는 경우 - 이미 삭제된 경우 #113 * test: FarmScheduleServiceTest - 농장이 삭제된 경우 예외를 발생 #113 * test: FarmScheduleServiceTest - 특정 날짜의 스케쥴 조회 #113 * test: FarmScheduleServiceTest - 중복된 스케줄이 있는 경우 save 메서드가 호출되지 않는다 #113 * test: FarmScheduleServiceTest - 스케줄이 없는 날짜에 대해 빈 리스트를 반환한다 #113 * test: FarmScheduleServiceTest - 특정 월에 해당하는 스케줄을 올바르게 조회한다 - 존재하지 않는 스케줄 ID로 조회 시 예외가 발생한다 #113 * test: 테스트 환경 키값 추가 - application-test.yml #113 * build: ci-test.yml 수정 - imp 키값 추가 #113 * build: ci-test.yml 수정 - imp 키값 추가 #113 * chore: 오타 수정 #113 * test: imp-key 값 추가 #113 * test: 테스트 실패 시 로그 남기도록 #113 * test: 테스트 실패 시 로그 남기도록 - 버전 업그레이드 #113 * build: 테스트 디비 추가 #113 * build: AWS 키값 추가 #113 * test: Iamport 모킹 설정 #113 * test: spring profile 설정 #113 --- .github/workflows/ci-test.yml | 20 +- .../java/poomasi/domain/farm/entity/Farm.java | 7 +- .../service/FarmScheduleServiceTest.java | 211 ++++++++++++++++++ .../farm/service/FarmFarmerServiceTest.java | 36 +++ .../domain/farm/service/FarmServiceTest.java | 13 ++ .../payment/iamportTest/IamportTest.java | 44 ++-- .../config/s3/S3PresignedUrlServiceTest.java | 2 +- src/test/resources/application-test.yml | 16 ++ 8 files changed, 324 insertions(+), 25 deletions(-) create mode 100644 src/test/java/poomasi/domain/farm/_schedule/service/FarmScheduleServiceTest.java create mode 100644 src/test/resources/application-test.yml diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 4e8b8de5..5b739bfb 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -11,6 +11,11 @@ permissions: jobs: test: + env: + IMP_API_KEY: ${{ secrets.IMP_API_KEY }} + IMP_SECRET_KEY: ${{ secrets.IMP_SECRET_KEY }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} runs-on: ubuntu-latest steps: - name: Checkout code @@ -21,6 +26,9 @@ jobs: with: java-version: '21' distribution: 'adopt' + env: + IMP_API_KEY: ${{ secrets.IMP_API_KEY }} + IMP_SECRET_KEY: ${{ secrets.IMP_SECRET_KEY }} - name: Cache Gradle packages uses: actions/cache@v3 @@ -29,12 +37,22 @@ jobs: key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | ${{ runner.os }}-gradle- + env: + IMP_API_KEY: ${{ secrets.IMP_API_KEY }} + IMP_SECRET_KEY: ${{ secrets.IMP_SECRET_KEY }} + + - name: Upload test report + if: always() + uses: actions/upload-artifact@v3 + with: + name: test-report + path: build/reports/tests/test - name: Grant execute permission for gradlew run: chmod +x ./gradlew - name: Run tests - run: ./gradlew test + run: SPRING_PROFILES_ACTIVE=[test] ./gradlew test env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/src/main/java/poomasi/domain/farm/entity/Farm.java b/src/main/java/poomasi/domain/farm/entity/Farm.java index 22c7b6c1..9e278c2d 100644 --- a/src/main/java/poomasi/domain/farm/entity/Farm.java +++ b/src/main/java/poomasi/domain/farm/entity/Farm.java @@ -85,7 +85,7 @@ public class Farm { private OrderedFarm orderedFarm; @Builder - public Farm(Long id, String name, Long ownerId, String address, String addressDetail, Double latitude, Double longitude, String description, int experiencePrice, Integer maxCapacity, Integer maxReservation) { + public Farm(Long id, String name, Long ownerId, String address, String addressDetail, Double latitude, Double longitude, String description, int experiencePrice, Integer maxCapacity, Integer maxReservation, LocalDateTime deletedAt) { this.id = id; this.name = name; this.ownerId = ownerId; @@ -97,6 +97,7 @@ public Farm(Long id, String name, Long ownerId, String address, String addressDe this.experiencePrice = experiencePrice; this.maxCapacity = maxCapacity; this.maxReservation = maxReservation; + this.deletedAt = deletedAt; } public Farm updateFarm(FarmUpdateRequest farmUpdateRequest) { @@ -120,4 +121,8 @@ public void updateMaxCapacity(Integer maxCapacity) { public void updateMaxReservation(Integer maxReservation) { this.maxReservation = maxReservation; } + + public void delete() { + this.deletedAt = LocalDateTime.now(); + } } diff --git a/src/test/java/poomasi/domain/farm/_schedule/service/FarmScheduleServiceTest.java b/src/test/java/poomasi/domain/farm/_schedule/service/FarmScheduleServiceTest.java new file mode 100644 index 00000000..7a611950 --- /dev/null +++ b/src/test/java/poomasi/domain/farm/_schedule/service/FarmScheduleServiceTest.java @@ -0,0 +1,211 @@ +package poomasi.domain.farm._schedule.service; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import poomasi.domain.farm._schedule.dto.FarmScheduleRequest; +import poomasi.domain.farm._schedule.dto.FarmScheduleResponse; +import poomasi.domain.farm._schedule.dto.FarmScheduleUpdateRequest; +import poomasi.domain.farm._schedule.entity.FarmSchedule; +import poomasi.domain.farm._schedule.repository.FarmScheduleRepository; +import poomasi.global.error.BusinessException; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static poomasi.global.error.BusinessError.*; + +@ExtendWith(MockitoExtension.class) +class FarmScheduleServiceTest { + @InjectMocks + private FarmScheduleService farmScheduleService; + + @Mock + private FarmScheduleRepository farmScheduleRepository; + + @Nested + @DisplayName("농장 스케줄 추가") + class AddFarmSchedule { + @Test + @DisplayName("정상적으로 스케줄을 추가한다") + void should_addFarmSchedule() { + // given + FarmScheduleUpdateRequest request = new FarmScheduleUpdateRequest(1L, LocalDate.now(), LocalTime.of(10, 0), LocalTime.of(12, 0)); + + given(farmScheduleRepository.findByFarmIdAndDate(1L, LocalDate.now())).willReturn(List.of()); + + // when + farmScheduleService.addFarmSchedule(request); + + // then + FarmSchedule farmSchedule = FarmSchedule.builder() + .farmId(1L) + .date(LocalDate.now()) + .startTime(LocalTime.of(10, 0)) + .endTime(LocalTime.of(12, 0)) + .build(); + assertAll( + () -> assertEquals(1L, farmSchedule.getFarmId()), + () -> assertEquals(LocalDate.now(), farmSchedule.getDate()), + () -> assertEquals(LocalTime.of(10, 0), farmSchedule.getStartTime()), + () -> assertEquals(LocalTime.of(12, 0), farmSchedule.getEndTime()) + ); + } + + @Test + @DisplayName("시작 시간이 종료 시간보다 늦은 경우 예외를 발생시킨다") + void should_throwException_when_startTimeIsAfterEndTime() { + // given + FarmScheduleUpdateRequest request = new FarmScheduleUpdateRequest(1L, LocalDate.now(), LocalTime.of(10, 0), LocalTime.of(9, 0)); + + // when & then + BusinessException exception = assertThrows(BusinessException.class, () -> farmScheduleService.addFarmSchedule(request)); + assertEquals(START_TIME_SHOULD_BE_BEFORE_END_TIME, exception.getBusinessError()); + } + + @Test + @DisplayName("이미 등록된 스케줄이 있는 경우 예외를 발생시킨다") + void should_throwException_when_scheduleAlreadyExists() { + // given + FarmSchedule farmSchedule = FarmSchedule.builder() + .startTime(LocalTime.of(10, 0)) + .endTime(LocalTime.of(12, 0)) + .build(); + List farmSchedules = List.of(farmSchedule); + + given(farmScheduleRepository.findByFarmIdAndDate(1L, LocalDate.now())).willReturn(farmSchedules); + + FarmScheduleUpdateRequest request = new FarmScheduleUpdateRequest(1L, LocalDate.now(), LocalTime.of(11, 0), LocalTime.of(13, 0)); + + // when & then + BusinessException exception = assertThrows(BusinessException.class, () -> farmScheduleService.addFarmSchedule(request)); + assertEquals(FARM_SCHEDULE_ALREADY_EXISTS, exception.getBusinessError()); + } + + @Test + @DisplayName("중복된 스케줄이 있는 경우 save 메서드가 호출되지 않는다") + void should_notCallSave_when_scheduleAlreadyExists() { + // given + FarmSchedule farmSchedule = FarmSchedule.builder() + .startTime(LocalTime.of(10, 0)) + .endTime(LocalTime.of(12, 0)) + .build(); + List farmSchedules = List.of(farmSchedule); + + given(farmScheduleRepository.findByFarmIdAndDate(1L, LocalDate.now())).willReturn(farmSchedules); + + FarmScheduleUpdateRequest request = new FarmScheduleUpdateRequest(1L, LocalDate.now(), LocalTime.of(11, 0), LocalTime.of(13, 0)); + + // when & then + assertThrows(BusinessException.class, () -> farmScheduleService.addFarmSchedule(request)); + verify(farmScheduleRepository, never()).save(any(FarmSchedule.class)); + } + } + + @Nested + @DisplayName("농장 스케줄 조회") + class GetFarmSchedules { + @Test + @DisplayName("텅 빈 스케줄을 조회한다") + void should_getEmptyFarmSchedules() { + // given + LocalDate date = LocalDate.now(); + given(farmScheduleRepository.findByFarmIdAndDate(1L, date)).willReturn(List.of()); + + // when + List farmSchedules = farmScheduleService.getFarmScheduleByFarmIdAndDate(1L, date); + + // then + assertTrue(farmSchedules.isEmpty()); + } + + @Test + @DisplayName("특정 날짜의 스케줄을 조회한다") + void should_getFarmSchedulesBySpecificDate() { + // given + LocalDate date = LocalDate.now(); + FarmSchedule farmSchedule = FarmSchedule.builder() + .farmId(1L) + .date(date) + .startTime(LocalTime.of(10, 0)) + .endTime(LocalTime.of(12, 0)) + .build(); + given(farmScheduleRepository.findByFarmIdAndDate(1L, date)).willReturn(List.of(farmSchedule)); + + // when + List farmSchedules = farmScheduleService.getFarmScheduleByFarmIdAndDate(1L, date); + + // then + assertAll( + () -> assertEquals(1, farmSchedules.size()), + () -> assertEquals(1L, farmSchedules.get(0).getFarmId()), + () -> assertEquals(date, farmSchedules.get(0).getDate()), + () -> assertEquals(LocalTime.of(10, 0), farmSchedules.get(0).getStartTime()), + () -> assertEquals(LocalTime.of(12, 0), farmSchedules.get(0).getEndTime()) + ); + } + + @Test + @DisplayName("스케줄이 없는 날짜에 대해 빈 리스트를 반환한다") + void should_returnEmptyList_when_noSchedulesOnDate() { + // given + LocalDate date = LocalDate.of(2024, 11, 12); + given(farmScheduleRepository.findByFarmIdAndDate(1L, date)).willReturn(List.of()); + + // when + List result = farmScheduleService.getFarmScheduleByFarmIdAndDate(1L, date); + + // then + assertTrue(result.isEmpty()); + } + + @Test + @DisplayName("특정 월에 해당하는 스케줄을 올바르게 조회한다") + void should_returnSchedulesWithinSpecifiedMonth() { + // given + LocalDate startDate = LocalDate.of(2024, 11, 1); + LocalDate endDate = LocalDate.of(2024, 11, 30); + FarmSchedule farmSchedule = FarmSchedule.builder() + .farmId(1L) + .date(LocalDate.of(2024, 11, 10)) + .startTime(LocalTime.of(10, 0)) + .endTime(LocalTime.of(12, 0)) + .build(); + + given(farmScheduleRepository.findByFarmIdAndDateRange(1L, startDate, endDate)).willReturn(List.of(farmSchedule)); + + // when + FarmScheduleRequest request = new FarmScheduleRequest(1L, 2024, 11); + List result = farmScheduleService.getFarmSchedulesByYearAndMonth(request); + + // then + assertEquals(1, result.size()); + assertEquals(farmSchedule.getDate(), result.get(0).date()); + assertEquals(farmSchedule.getStartTime(), result.get(0).startTime()); + assertEquals(farmSchedule.getEndTime(), result.get(0).endTime()); + } + + @Test + @DisplayName("존재하지 않는 스케줄 ID로 조회 시 예외가 발생한다") + void should_throwException_when_scheduleIdNotFound() { + // given + Long invalidId = 999L; + given(farmScheduleRepository.findById(invalidId)).willReturn(Optional.empty()); + + // when & then + BusinessException exception = assertThrows(BusinessException.class, () -> farmScheduleService.getFarmScheduleByScheduleId(invalidId)); + assertEquals(FARM_SCHEDULE_NOT_FOUND, exception.getBusinessError()); + } + } +} diff --git a/src/test/java/poomasi/domain/farm/service/FarmFarmerServiceTest.java b/src/test/java/poomasi/domain/farm/service/FarmFarmerServiceTest.java index 3fc65918..b6d3ac62 100644 --- a/src/test/java/poomasi/domain/farm/service/FarmFarmerServiceTest.java +++ b/src/test/java/poomasi/domain/farm/service/FarmFarmerServiceTest.java @@ -137,5 +137,41 @@ void should_deleteFarm_when_ownerMatches() { // then verify(farmRepository).delete(farm); } + + @Test + @DisplayName("농장이 존재하지 않는 경우 예외를 발생시킨다") + void should_throwException_when_farmNotExistOnDelete() { + // given + Long farmId = 1L; + Long farmerId = 1L; + given(farmRepository.findByIdAndDeletedAtIsNull(farmId)).willReturn(Optional.empty()); + + // when & then + assertThatThrownBy(() -> farmFarmerService.deleteFarm(farmerId, farmId)) + .isInstanceOf(BusinessException.class) + .hasFieldOrPropertyWithValue("businessError", BusinessError.FARM_NOT_FOUND); + } + + @Test + @DisplayName("농장이 이미 삭제된 경우 예외를 발생시킨다") + void should_throwException_when_farmAlreadyDeleted() { + // given + Long farmId = 1L; + Long farmerId = 1L; + Farm farm = Farm.builder() + .id(farmId) + .name("Farm") + .ownerId(farmerId) + .deletedAt(null) + .build(); + + given(farmRepository.findByIdAndDeletedAtIsNull(farmId)).willReturn(Optional.of(farm)); + + // when + farmFarmerService.deleteFarm(farmerId, farmId); + + // then + verify(farmRepository).delete(farm); + } } } diff --git a/src/test/java/poomasi/domain/farm/service/FarmServiceTest.java b/src/test/java/poomasi/domain/farm/service/FarmServiceTest.java index cc9603f0..a24ae9a0 100644 --- a/src/test/java/poomasi/domain/farm/service/FarmServiceTest.java +++ b/src/test/java/poomasi/domain/farm/service/FarmServiceTest.java @@ -58,6 +58,19 @@ void should_throwException_when_farmNotExist() { .isInstanceOf(BusinessException.class) .hasFieldOrPropertyWithValue("businessError", BusinessError.FARM_NOT_FOUND); } + + @Test + @DisplayName("농장이 삭제된 경우 예외를 발생시킨다") + void should_throwException_when_farmIsDeleted() { + // given + Farm farm = FarmTestHelper.makeRandomFarm(); + farm.delete(); + + // when & then + assertThatThrownBy(() -> farmService.getFarmByFarmId(farm.getId())) + .isInstanceOf(BusinessException.class) + .hasFieldOrPropertyWithValue("businessError", BusinessError.FARM_NOT_FOUND); + } } } diff --git a/src/test/java/poomasi/domain/payment/iamportTest/IamportTest.java b/src/test/java/poomasi/domain/payment/iamportTest/IamportTest.java index 2d3df7bd..9d0ac2f4 100644 --- a/src/test/java/poomasi/domain/payment/iamportTest/IamportTest.java +++ b/src/test/java/poomasi/domain/payment/iamportTest/IamportTest.java @@ -3,57 +3,57 @@ import com.siot.IamportRestClient.IamportClient; import com.siot.IamportRestClient.exception.IamportResponseException; import com.siot.IamportRestClient.request.PrepareData; -import com.siot.IamportRestClient.response.AccessToken; import com.siot.IamportRestClient.response.IamportResponse; -import com.siot.IamportRestClient.response.Payment; import com.siot.IamportRestClient.response.Prepare; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.web.client.RestTemplate; -import poomasi.domain.order._payment.dto.request.PaymentPreRegisterRequest; -import poomasi.domain.order._payment.dto.response.PaymentPreRegisterResponse; - +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; import java.io.IOException; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import static com.fasterxml.jackson.databind.type.LogicalType.DateTime; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +@SpringBootTest +@ActiveProfiles("test") +@TestPropertySource(locations = "classpath:application-test.yml") public class IamportTest { + @MockBean private IamportClient iamportClient; - private String apiKey="~"; - private String secretKey="~"; - private String accessToken; + @Value("${imp.api.key}") + private String apiKey; + + @Value("${imp.api.secretKey}") + private String secretKey; @BeforeEach - public void setUp() throws Exception { + public void setUp() { this.iamportClient = new IamportClient(apiKey, secretKey); - IamportResponse auth_response = iamportClient.getAuth(); - this.accessToken=auth_response.getResponse().getToken(); } @Test - public void portonePrePaymentRegister_Test() throws IamportResponseException ,IOException{ + public void portonePrePaymentRegister_Test() throws IamportResponseException, IOException { String merchantUid = "poomasi_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); BigDecimal amount = new BigDecimal("100"); PrepareData prepareData = new PrepareData(merchantUid, amount); - System.out.println(merchantUid); + // `iamportClient.postPrepare` 모킹 설정 + IamportResponse mockResponse = new IamportResponse<>(); + given(iamportClient.postPrepare(any(PrepareData.class))).willReturn(mockResponse); + + // 테스트 실행 IamportResponse prepareIamportResponse = iamportClient.postPrepare(prepareData); System.out.println("Response Code: " + prepareIamportResponse.getCode()); System.out.println("Response Message: " + prepareIamportResponse.getMessage()); - } - } diff --git a/src/test/java/poomasi/global/config/s3/S3PresignedUrlServiceTest.java b/src/test/java/poomasi/global/config/s3/S3PresignedUrlServiceTest.java index 7bf948ae..d98d9ea6 100644 --- a/src/test/java/poomasi/global/config/s3/S3PresignedUrlServiceTest.java +++ b/src/test/java/poomasi/global/config/s3/S3PresignedUrlServiceTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; import poomasi.global.config.aws.AwsProperties; import poomasi.global.util.EncryptionUtil; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; @@ -18,7 +19,6 @@ @SpringBootTest public class S3PresignedUrlServiceTest { - private S3PresignedUrlService s3PresignedUrlService; @Autowired diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml new file mode 100644 index 00000000..51b36f18 --- /dev/null +++ b/src/test/resources/application-test.yml @@ -0,0 +1,16 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + driver-class-name: org.h2.Driver + username: sa + password: + jpa: + hibernate: + ddl-auto: update + show-sql: true + +imp: + api: + key: ${IMP_API_KEY} + secretKey: ${IMP_SECRET_KEY} + From 4224f60c5212634823c932357fdf6201eba905e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EC=A7=84=ED=83=9D?= <87135698+jjt4515@users.noreply.github.com> Date: Tue, 12 Nov 2024 15:58:14 +0900 Subject: [PATCH 17/26] =?UTF-8?q?fix:=20MemberProfileResponse=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EC=A0=9C=EA=B1=B0=20#82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/MemberProfileResponse.java | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 src/main/java/poomasi/domain/member/dto/response/MemberProfileResponse.java diff --git a/src/main/java/poomasi/domain/member/dto/response/MemberProfileResponse.java b/src/main/java/poomasi/domain/member/dto/response/MemberProfileResponse.java deleted file mode 100644 index 9a36d9e7..00000000 --- a/src/main/java/poomasi/domain/member/dto/response/MemberProfileResponse.java +++ /dev/null @@ -1,29 +0,0 @@ -package poomasi.domain.member.dto.response; - -import poomasi.domain.member.entity.MemberProfile; - -import java.time.LocalDateTime; - -public record MemberProfileResponse( - String name, - String phoneNumber, - String address, - String addressDetail, - Long coordinateX, - Long coordinateY, - boolean isBanned, - LocalDateTime createdAt -) { - public static MemberProfileResponse fromEntity(MemberProfile profile) { - return new MemberProfileResponse( - profile.getName(), - profile.getPhoneNumber(), - profile.getAddress(), - profile.getAddressDetail(), - profile.getCoordinateX(), - profile.getCoordinateY(), - profile.isBanned(), - profile.getCreatedAt() - ); - } -} \ No newline at end of file From 6b88f4cc2335bf6c57ecd73ef5bca351c77e8c9f Mon Sep 17 00:00:00 2001 From: amm0124 Date: Tue, 12 Nov 2024 17:49:41 +0900 Subject: [PATCH 18/26] =?UTF-8?q?feat=20:=20test=20service(=EC=9E=84?= =?UTF-8?q?=EC=8B=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/poomasi/domain/auth/security/AuthTestService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/poomasi/domain/auth/security/AuthTestService.java b/src/main/java/poomasi/domain/auth/security/AuthTestService.java index 1a6e21be..7a237b38 100644 --- a/src/main/java/poomasi/domain/auth/security/AuthTestService.java +++ b/src/main/java/poomasi/domain/auth/security/AuthTestService.java @@ -11,6 +11,8 @@ @Service public class AuthTestService { + //제가 테스트하려고 만든 건데 다음 pr때 지우겠습니다 + public String Test(){ Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Object impl = authentication.getPrincipal(); From aa9be8af0734d6a1bcc48c08514ddba27f76bda2 Mon Sep 17 00:00:00 2001 From: amm0124 Date: Tue, 12 Nov 2024 17:50:32 +0900 Subject: [PATCH 19/26] =?UTF-8?q?feat=20:=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/security/userdetail/UserDetailsImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/poomasi/domain/auth/security/userdetail/UserDetailsImpl.java b/src/main/java/poomasi/domain/auth/security/userdetail/UserDetailsImpl.java index 629e425d..ca9e5499 100644 --- a/src/main/java/poomasi/domain/auth/security/userdetail/UserDetailsImpl.java +++ b/src/main/java/poomasi/domain/auth/security/userdetail/UserDetailsImpl.java @@ -25,7 +25,7 @@ public UserDetailsImpl(Member member) { this.member = member; } - public UserDetailsImpl(Member member, Map attributes ) { + public UserDetailsImpl(Member member, Map attributes){ this.member = member; this.attributes = attributes; } @@ -75,7 +75,6 @@ public boolean isCredentialsNonExpired() { return true; } - //Oauth2 member name @Override public String getName() { return null; From 977054ccba6d8807df059ad949426f9a35b3ead1 Mon Sep 17 00:00:00 2001 From: amm0124 Date: Tue, 12 Nov 2024 17:54:08 +0900 Subject: [PATCH 20/26] =?UTF-8?q?feat=20:=20security=20config=20oauth2=20?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/SecurityConfig.java | 49 +++++++------------ 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/src/main/java/poomasi/domain/auth/config/SecurityConfig.java b/src/main/java/poomasi/domain/auth/config/SecurityConfig.java index 14acee13..c2a3f1a5 100644 --- a/src/main/java/poomasi/domain/auth/config/SecurityConfig.java +++ b/src/main/java/poomasi/domain/auth/config/SecurityConfig.java @@ -78,23 +78,28 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers(HttpMethod.GET, "/api/review/**").permitAll() .requestMatchers(HttpMethod.GET, "/health").permitAll() .requestMatchers(HttpMethod.GET, "/api/image/**").permitAll() - .requestMatchers("/api/sign-up", "/api/login", "api/reissue", "api/payment/**", "api/order/**", "api/reservation/**", "/api/v1/farmer/reservations").permitAll() + .requestMatchers("/api/member/sign-up", "/api/login", "api/reissue", "api/payment/**", "api/order/**", "api/reservation/**", "/api/v1/farmer/reservations").permitAll() .requestMatchers("/api/need-auth/**").authenticated() .anyRequest(). authenticated() ); - /* - http.authorizeHttpRequests((authorize) -> authorize - .requestMatchers("/**").permitAll() - .requestMatchers("/api/auth-test/**", - "/api/cart/**", - "/api/order/**", - "/api/payment/**").authenticated() - .anyRequest() - .authenticated() - ); - */ + + //endpoint : {domain}/oauth2/authentication/kakao + http + .oauth2Login((oauth2) -> oauth2 + .userInfoEndpoint((userInfoEndpointConfig) -> userInfoEndpointConfig + .userService(oAuth2UserDetailServiceImpl)) + .successHandler(customSuccessHandler) + ); + + CustomUsernamePasswordAuthenticationFilter customUsernameFilter = + new CustomUsernamePasswordAuthenticationFilter(authenticationManager(authenticationConfiguration), jwtUtil); + customUsernameFilter.setFilterProcessesUrl("/api/login"); + + http.addFilterAt(customUsernameFilter, UsernamePasswordAuthenticationFilter.class); + http.addFilterBefore(new JwtAuthenticationFilter(jwtUtil, userDetailsService), UsernamePasswordAuthenticationFilter.class); + /* 로그아웃 필터 등록하기 LogoutHandler[] handlers = { @@ -114,26 +119,6 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti ); */ - /* - oauth2 인증은 현재 해제해놨습니다 -> 차후 code를 front에서 어떤 경로로 받을 것인지 - 아니면 kakao에서 바로 redirect를 백엔드로 할 지 정해지면 - processing url 작성하겠습니다 - */ - http - .oauth2Login((oauth2) -> oauth2 - .userInfoEndpoint((userInfoEndpointConfig) -> userInfoEndpointConfig - .userService(oAuth2UserDetailServiceImpl)) - .successHandler(customSuccessHandler) - ); - - http.oauth2Login(AbstractHttpConfigurer::disable); - - CustomUsernamePasswordAuthenticationFilter customUsernameFilter = - new CustomUsernamePasswordAuthenticationFilter(authenticationManager(authenticationConfiguration), jwtUtil); - customUsernameFilter.setFilterProcessesUrl("/api/login"); - - http.addFilterAt(customUsernameFilter, UsernamePasswordAuthenticationFilter.class); - http.addFilterBefore(new JwtAuthenticationFilter(jwtUtil, userDetailsService), UsernamePasswordAuthenticationFilter.class); //http.addFilterAfter(customLogoutFilter, JwtAuthenticationFilter.class); return http.build(); From 5c43e081169eceb504906cb475f029ef814dbfb6 Mon Sep 17 00:00:00 2001 From: amm0124 Date: Tue, 12 Nov 2024 17:54:18 +0900 Subject: [PATCH 21/26] =?UTF-8?q?feat=20:=20security=20config=20oauth2=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EB=B0=9C=EA=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/CustomSuccessHandler.java | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/main/java/poomasi/domain/auth/security/handler/CustomSuccessHandler.java b/src/main/java/poomasi/domain/auth/security/handler/CustomSuccessHandler.java index 829e00bd..1f944bbd 100644 --- a/src/main/java/poomasi/domain/auth/security/handler/CustomSuccessHandler.java +++ b/src/main/java/poomasi/domain/auth/security/handler/CustomSuccessHandler.java @@ -11,31 +11,49 @@ import jakarta.servlet.http.HttpServletResponse; import jdk.jfr.Description; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.stereotype.Component; +import poomasi.domain.auth.security.userdetail.UserDetailsImpl; +import poomasi.domain.auth.token.util.JwtUtil; +import poomasi.domain.member.entity.Member; import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; @Slf4j @Component -public class CustomSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { +public class CustomSuccessHandler implements AuthenticationSuccessHandler { + + private final JwtUtil jwtUtil; + + public CustomSuccessHandler(JwtUtil jwtUtil) { + this.jwtUtil = jwtUtil; + } @Description("TODO : Oauth2.0 로그인이 성공하면 server access, refresh token을 발급하는 메서드") @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + log.info("[Oauth2 success handler] - OAuth2 로그인 성공적으로 완료되었습니다. access/refresh token 발급합니다."); - // 로직은 완성되었습니다 ~ - // Oauth2.0 로그인이 성공하면 server access, refresh token을 발급하는 메서드 - // - log.info("Oauth2 success handler."); - response.setHeader("access", ""); - response.addCookie(createCookie("refresh", "")); - response.setStatus(HttpStatus.OK.value()); + UserDetailsImpl userDetailsImpl = (UserDetailsImpl) authentication.getPrincipal(); + Member member = userDetailsImpl.getMember(); + Long memberId = member.getId(); + + String accessToken = jwtUtil.generateAccessTokenById(memberId); + String refreshToken = jwtUtil.generateRefreshTokenById(memberId); + response.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); + response.setStatus(HttpStatus.OK.value()); + response.addCookie(createCookie("refresh", refreshToken)); + response.getWriter(); } private Cookie createCookie(String key, String value) { From 82f13ae082672df17207272ecc2e0585a508136a Mon Sep 17 00:00:00 2001 From: amm0124 Date: Tue, 12 Nov 2024 17:54:39 +0900 Subject: [PATCH 22/26] =?UTF-8?q?feat=20:=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=EC=95=88=20=EC=93=B0=EB=8A=94=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../userdetail/OAuth2UserDetailServiceImpl.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/java/poomasi/domain/auth/security/userdetail/OAuth2UserDetailServiceImpl.java b/src/main/java/poomasi/domain/auth/security/userdetail/OAuth2UserDetailServiceImpl.java index a595b326..e3923435 100644 --- a/src/main/java/poomasi/domain/auth/security/userdetail/OAuth2UserDetailServiceImpl.java +++ b/src/main/java/poomasi/domain/auth/security/userdetail/OAuth2UserDetailServiceImpl.java @@ -18,7 +18,6 @@ import java.util.Map; @Service -@Description("소셜 서비스와 로컬 계정 연동 할 것이라면 여기서 연동 해야 함") @Slf4j public class OAuth2UserDetailServiceImpl extends DefaultOAuth2UserService { @@ -44,33 +43,29 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic } else{ log.warn("지원하지 않은 로그인 서비스 입니다."); } - + + // 정보 추출 String providerId = oAuth2UserInfo.getProviderId(); String email = oAuth2UserInfo.getEmail(); Role role = Role.ROLE_CUSTOMER; LoginType loginType = oAuth2UserInfo.getLoginType(); - - - //일단 없으면 가입시키는 쪽으로 구현ㄴ + + // 카카오 로그인을 처음 한 상태라면 회원가입 Member member = memberRepository.findByEmailAndDeletedAtIsNull(email).orElse(null); if(member == null) { member = Member.builder() .email(email) .role(role) - .loginType(loginType) // loginType에 맞게 변경 + .loginType(loginType) .provideId(providerId) .memberProfile(new MemberProfile()) .build(); memberRepository.save(member); - } //있다면 그냥 member 등록하기 - if(member.getLoginType()==LoginType.LOCAL){ - //member.setProviderId(providerId); -> 로그인 시 Id 조회함 - } // 카카오 회원으로 로그인이 되어 있다면 -> context에 저장 return new UserDetailsImpl(member, oAuth2User.getAttributes()); From 5e04adb27849a4764119657deb8e716b74c30427 Mon Sep 17 00:00:00 2001 From: amm0124 Date: Tue, 12 Nov 2024 19:54:28 +0900 Subject: [PATCH 23/26] =?UTF-8?q?feat=20:=20cors=20=EC=84=A4=EC=A0=95=20-?= =?UTF-8?q?=20react=203000=EB=B2=88=20=ED=8F=AC=ED=8A=B8=20-=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8(=ED=94=84=EB=A1=A0=ED=8A=B8)=20=EB=B0=8F=20?= =?UTF-8?q?=EC=84=9C=EB=B8=8C=EB=8F=84=EB=A9=94=EC=9D=B8(=EB=B0=B1?= =?UTF-8?q?=EC=97=94=EB=93=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/config/CorsConfig.java | 36 +++++++++++++++++++ .../domain/auth/config/SecurityConfig.java | 14 ++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 src/main/java/poomasi/domain/auth/config/CorsConfig.java diff --git a/src/main/java/poomasi/domain/auth/config/CorsConfig.java b/src/main/java/poomasi/domain/auth/config/CorsConfig.java new file mode 100644 index 00000000..fe09e981 --- /dev/null +++ b/src/main/java/poomasi/domain/auth/config/CorsConfig.java @@ -0,0 +1,36 @@ +package poomasi.domain.auth.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import java.util.Arrays; + +@Configuration +public class CorsConfig { + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration config = new CorsConfiguration(); + + // 허용할 origin 목록 설정 + config.setAllowedOrigins(Arrays.asList( + "https://localhost:3000", + "https://poomasi.shop", + "https://*.poomasi.shop" + )); + + config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE")); + config.setAllowedHeaders(Arrays.asList("*")); + config.setAllowCredentials(true); + config.setExposedHeaders(Arrays.asList("Set-Cookie", "Authorization")); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); // 모든 경로에 대해 적용 + + return source; + } +} + diff --git a/src/main/java/poomasi/domain/auth/config/SecurityConfig.java b/src/main/java/poomasi/domain/auth/config/SecurityConfig.java index c2a3f1a5..77fb6413 100644 --- a/src/main/java/poomasi/domain/auth/config/SecurityConfig.java +++ b/src/main/java/poomasi/domain/auth/config/SecurityConfig.java @@ -1,6 +1,8 @@ package poomasi.domain.auth.config; +import jakarta.servlet.http.HttpServletRequest; import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -18,6 +20,9 @@ import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import poomasi.domain.auth.security.filter.CustomUsernamePasswordAuthenticationFilter; import poomasi.domain.auth.security.filter.JwtAuthenticationFilter; import poomasi.domain.auth.security.handler.CustomSuccessHandler; @@ -26,6 +31,9 @@ import poomasi.domain.auth.security.userdetail.UserDetailsServiceImpl; import poomasi.domain.auth.token.util.JwtUtil; +import java.util.Arrays; +import java.util.Collections; + @AllArgsConstructor @Configuration @@ -38,6 +46,7 @@ public class SecurityConfig { private final MvcRequestMatcher.Builder mvc; private final CustomSuccessHandler customSuccessHandler; private final UserDetailsServiceImpl userDetailsService; + private final CorsConfigurationSource corsConfigurationSource; @Autowired private OAuth2UserDetailServiceImpl oAuth2UserDetailServiceImpl; @@ -60,8 +69,9 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti //csrf 해제 http.csrf(AbstractHttpConfigurer::disable); - //cors 해제 - http.cors(AbstractHttpConfigurer::disable); + //cors 설정 + http.cors(cors -> cors + .configurationSource(corsConfigurationSource)); //세션 해제 http.sessionManagement((session) -> session From f1c08af835c3b27c6ec8b8e979fce5a892c98aad Mon Sep 17 00:00:00 2001 From: amm0124 Date: Tue, 12 Nov 2024 20:32:30 +0900 Subject: [PATCH 24/26] =?UTF-8?q?feat=20:=20cors=20=EC=84=A4=EC=A0=95=20-?= =?UTF-8?q?=20react=203000=EB=B2=88=20=ED=8F=AC=ED=8A=B8=20-=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8(=ED=94=84=EB=A1=A0=ED=8A=B8)=20=EB=B0=8F=20?= =?UTF-8?q?=EC=84=9C=EB=B8=8C=EB=8F=84=EB=A9=94=EC=9D=B8(=EB=B0=B1?= =?UTF-8?q?=EC=97=94=EB=93=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/security/handler/CustomSuccessHandler.java | 6 ++++-- src/main/java/poomasi/domain/auth/token/util/JwtUtil.java | 2 -- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/poomasi/domain/auth/security/handler/CustomSuccessHandler.java b/src/main/java/poomasi/domain/auth/security/handler/CustomSuccessHandler.java index 1f944bbd..c4f0c483 100644 --- a/src/main/java/poomasi/domain/auth/security/handler/CustomSuccessHandler.java +++ b/src/main/java/poomasi/domain/auth/security/handler/CustomSuccessHandler.java @@ -50,9 +50,11 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo String accessToken = jwtUtil.generateAccessTokenById(memberId); String refreshToken = jwtUtil.generateRefreshTokenById(memberId); - response.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); - response.setStatus(HttpStatus.OK.value()); response.addCookie(createCookie("refresh", refreshToken)); + response.addCookie(createCookie("access", accessToken)); + + response.setStatus(HttpStatus.OK.value()); + response.getWriter(); } diff --git a/src/main/java/poomasi/domain/auth/token/util/JwtUtil.java b/src/main/java/poomasi/domain/auth/token/util/JwtUtil.java index 46501256..397046d6 100644 --- a/src/main/java/poomasi/domain/auth/token/util/JwtUtil.java +++ b/src/main/java/poomasi/domain/auth/token/util/JwtUtil.java @@ -91,8 +91,6 @@ public String getEmailFromTokenInFilter(final String token) { return getClaimFromToken(token, "email", String.class); } - // <--------------------------------------------> - // 토큰 생성 public String generateAccessTokenById(final Long memberId) { Map claims = createClaims(memberId); From ce2ef0f37758be0f208ae7bd082f19eed7eec766 Mon Sep 17 00:00:00 2001 From: amm0124 Date: Tue, 12 Nov 2024 21:56:45 +0900 Subject: [PATCH 25/26] =?UTF-8?q?merge=20issue=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/_payment/entity/PaymentState.java | 31 ---- .../_payment/service/PaymentService.java | 149 ------------------ .../order/_payment/util/PaymentUtil.java | 6 +- .../domain/order/_refund/entity/Refund.java | 20 --- .../order/_refund/entity/RefundStatus.java | 29 ---- .../domain/order/entity/AbstractOrder.java | 33 ---- .../poomasi/domain/order/entity/Order.java | 49 ------ .../domain/order/entity/OrderDetails.java | 38 ----- .../order/entity/OrderProductDetails.java | 71 --------- .../domain/order/entity/OrderStatus.java | 11 -- .../OrderProductDetailsRepository.java | 10 -- .../order/repository/OrderRepository.java | 14 -- 12 files changed, 3 insertions(+), 458 deletions(-) delete mode 100644 src/main/java/poomasi/domain/order/_payment/entity/PaymentState.java delete mode 100644 src/main/java/poomasi/domain/order/_payment/service/PaymentService.java delete mode 100644 src/main/java/poomasi/domain/order/_refund/entity/Refund.java delete mode 100644 src/main/java/poomasi/domain/order/_refund/entity/RefundStatus.java delete mode 100644 src/main/java/poomasi/domain/order/entity/AbstractOrder.java delete mode 100644 src/main/java/poomasi/domain/order/entity/Order.java delete mode 100644 src/main/java/poomasi/domain/order/entity/OrderDetails.java delete mode 100644 src/main/java/poomasi/domain/order/entity/OrderProductDetails.java delete mode 100644 src/main/java/poomasi/domain/order/entity/OrderStatus.java delete mode 100644 src/main/java/poomasi/domain/order/repository/OrderProductDetailsRepository.java delete mode 100644 src/main/java/poomasi/domain/order/repository/OrderRepository.java diff --git a/src/main/java/poomasi/domain/order/_payment/entity/PaymentState.java b/src/main/java/poomasi/domain/order/_payment/entity/PaymentState.java deleted file mode 100644 index 77d04d38..00000000 --- a/src/main/java/poomasi/domain/order/_payment/entity/PaymentState.java +++ /dev/null @@ -1,31 +0,0 @@ -package poomasi.domain.order._payment.entity; - -public enum PaymentState { - PENDING, // 결제 대기 중 - COMPLETED, // 결제 완료 - FAILED, // 결제 실패 - CANCELLED, // 결제 취소됨 - REFUNDED, // 환불 완료 - DECLINED; // 결제 거부됨 - - @Override - public String toString() { - // 사용자 친화적인 문자열로 반환할 수 있도록 오버라이딩 - switch (this) { - case PENDING: - return "Payment Pending"; - case COMPLETED: - return "Payment Completed"; - case FAILED: - return "Payment Failed"; - case CANCELLED: - return "Payment Cancelled"; - case REFUNDED: - return "Payment Refunded"; - case DECLINED: - return "Payment Declined"; - default: - return super.toString(); - } - } -} diff --git a/src/main/java/poomasi/domain/order/_payment/service/PaymentService.java b/src/main/java/poomasi/domain/order/_payment/service/PaymentService.java deleted file mode 100644 index e5d33028..00000000 --- a/src/main/java/poomasi/domain/order/_payment/service/PaymentService.java +++ /dev/null @@ -1,149 +0,0 @@ -package poomasi.domain.order._payment.service; - -import com.siot.IamportRestClient.IamportClient; -import com.siot.IamportRestClient.exception.IamportResponseException; -import com.siot.IamportRestClient.request.CancelData; -import com.siot.IamportRestClient.request.PrepareData; -import com.siot.IamportRestClient.response.AccessToken; -import com.siot.IamportRestClient.response.IamportResponse; -import com.siot.IamportRestClient.response.Prepare; -import jdk.jfr.Description; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import poomasi.domain.auth.security.userdetail.UserDetailsImpl; -import poomasi.domain.member.entity.Member; -import poomasi.domain.order._payment.dto.request.PaymentPreRegisterRequest; -import poomasi.domain.order._payment.dto.request.PaymentWebHookRequest; -import poomasi.domain.order._payment.dto.response.PaymentPreRegisterResponse; -import poomasi.domain.order._payment.dto.response.PaymentResponse; -import poomasi.domain.order._payment.entity.Payment; -import poomasi.domain.order._payment.repository.PaymentRepository; -import poomasi.domain.order.entity.Order; -import poomasi.domain.order.repository.OrderRepository; -import poomasi.domain.product._cart.service.CartService; -import poomasi.global.error.BusinessError; -import poomasi.global.error.BusinessException; - -import java.io.IOException; -import java.math.BigDecimal; -import java.util.List; - -import static poomasi.domain.order.entity.OrderStatus.AWAITING_SELLER_CONFIRMATION; -import static poomasi.domain.order.entity.OrderStatus.PENDING; -import static poomasi.global.error.BusinessError.*; - -@Service -@RequiredArgsConstructor -@Slf4j -public class PaymentService { - - @Autowired - private final PaymentRepository paymentRepository; - private final IamportClient iamportClient; - private final OrderRepository orderRepository; - private final CartService cartService; - - @Description("포트원 api 호출을 위한 accessToken 발급 메서드") - private String getPortOneAccessToken() throws IOException, IamportResponseException { - IamportResponse authResponse = iamportClient.getAuth(); - String accessToken = authResponse.getResponse().getToken(); - return accessToken; - } - - @Description("사전 결제 등록") - public PaymentPreRegisterResponse portonePrePaymentRegister(PaymentPreRegisterRequest paymentPreRegisterRequest) throws IOException, IamportResponseException { - PrepareData prepareData = new PrepareData(paymentPreRegisterRequest.merchantUid(), - paymentPreRegisterRequest.amount() - ); - iamportClient.postPrepare(prepareData); - return PaymentPreRegisterResponse.from( - paymentPreRegisterRequest.merchantUid() - ); - } - - @Transactional - @Description("프론트에서 받아온 결과를 validate하는 메서드") - public void portoneVerifyPostPayment(PaymentWebHookRequest paymentWebHookRequest) throws IOException, IamportResponseException { - String impUid = paymentWebHookRequest.imp_uid(); - String merchantUid = paymentWebHookRequest.merchant_uid(); - IamportResponse iamportResponse = iamportClient.paymentByImpUid(impUid); - BigDecimal amount = iamportResponse.getResponse() - .getAmount(); - - Order order = orderRepository.findByMerchantUid(merchantUid) - .orElseThrow(() -> new BusinessException(ORDER_NOT_FOUND)); - - if(order.getOrderStatus()!=PENDING){ //이미 처리한 주문이라면 - throw new BusinessException(ORDER_ALREADY_PROCESSED); - } - - if(validatePaymentConsistency(order.getTotalAmount(), amount)){ //결제 금액이 맞지 않다면 -> 주문 취소 api 호출 - cancelPayment(iamportResponse); - throw new BusinessException(PAYMENT_AMOUNT_MISMATCH); - } - order.setOrderStatus(AWAITING_SELLER_CONFIRMATION); // 상태 변경 - cartService.removeSelected(); //장바구니 삭제 - } - - private boolean validatePaymentConsistency(BigDecimal prepaymentAmount, BigDecimal postPaymentAmount){ - if (prepaymentAmount.compareTo(postPaymentAmount) != 0) { - return false; - } - return true; - } - - @Description("payment 상세 내역 조회를 위한 단건 api 호출") - public void getPaymentDetails(String merchantUid, Long orderId) throws IOException, IamportResponseException { - - } - - @Description("결제 취소 api") - public void cancelPayment(IamportResponse response) throws IOException, IamportResponseException{ - //true면 Uid, false면 merchantUid로 판단 - CancelData cancelData = new CancelData(response.getResponse().getMerchantUid(), false); - iamportClient.cancelPaymentByImpUid(cancelData); - } - - @Description("결제 환불 api") - public void processRefund() throws IOException, IamportResponseException{ - - } - - - @Description("결제 부분 환불 api 호출") - public void partialRefund() throws IOException, IamportResponseException { - - } - - public PaymentResponse getPayment(Long paymentId) { - Payment payment = paymentRepository.findById(paymentId) - .orElseThrow(() -> new BusinessException(PAYMENT_NOT_FOUND)); - return PaymentResponse.fromEntity(payment); - } - - @Description("orderID로 결제 방법 찾는 메서드") - public PaymentResponse getPaymentByOrderId(Long orderId) { - Member member = getMember(); - Payment payment = paymentRepository.findById(orderId) - .orElseThrow(() -> new BusinessException(PAYMENT_NOT_FOUND)); - return PaymentResponse.fromEntity(payment); - } - - - private Member getMember() { - Authentication authentication = SecurityContextHolder - .getContext().getAuthentication(); - Object impl = authentication.getPrincipal(); - Member member = ((UserDetailsImpl) impl).getMember(); - return member; - } - -} - - diff --git a/src/main/java/poomasi/domain/order/_payment/util/PaymentUtil.java b/src/main/java/poomasi/domain/order/_payment/util/PaymentUtil.java index ce1d9212..c5c571d8 100644 --- a/src/main/java/poomasi/domain/order/_payment/util/PaymentUtil.java +++ b/src/main/java/poomasi/domain/order/_payment/util/PaymentUtil.java @@ -35,8 +35,8 @@ public BigDecimal getPaymentAmount(String impUid) throws IOException, IamportRes } @Description("단건 결제 조회 API") - public IamportResponse getSingleTransaction(String impUid) throws IOException, IamportResponseException { - IamportResponse iamportResponse = iamportClient.paymentByImpUid(impUid); + public IamportResponse getSingleTransaction(String impUid) throws IOException, IamportResponseException { + IamportResponse iamportResponse = iamportClient.paymentByImpUid(impUid); return iamportResponse; } @@ -73,7 +73,7 @@ public void sendPrepareData(String merchantUid, BigDecimal amount) throws IOExce @Description("단건 조회 후, 결제 되어야 할 금액과 결제 된 금액이 같은지 확인하는 메서드") public boolean validatePaymentAmount(String impUid, BigDecimal amountToBePaid) throws IOException, IamportResponseException{ - IamportResponse iamportResponse = getSingleTransaction(impUid); //내가 보냄 + IamportResponse iamportResponse = getSingleTransaction(impUid); //내가 보냄 BigDecimal amount = iamportResponse.getResponse().getAmount(); if(amountToBePaid.compareTo(amount)!=0){ return false; diff --git a/src/main/java/poomasi/domain/order/_refund/entity/Refund.java b/src/main/java/poomasi/domain/order/_refund/entity/Refund.java deleted file mode 100644 index 8b51294d..00000000 --- a/src/main/java/poomasi/domain/order/_refund/entity/Refund.java +++ /dev/null @@ -1,20 +0,0 @@ -package poomasi.domain.order._refund.entity; - - -import jakarta.persistence.*; -import poomasi.domain.order.entity.OrderProductDetails; - -@Entity -@Table(name="refund") -public class Refund { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - -/* @OneToOne(fetch = FetchType.LAZY) - private OrderProductDetails orderProductDetails;*/ - - private String refundReason; - -} diff --git a/src/main/java/poomasi/domain/order/_refund/entity/RefundStatus.java b/src/main/java/poomasi/domain/order/_refund/entity/RefundStatus.java deleted file mode 100644 index 69a08f7c..00000000 --- a/src/main/java/poomasi/domain/order/_refund/entity/RefundStatus.java +++ /dev/null @@ -1,29 +0,0 @@ -package poomasi.domain.order._refund.entity; - -public enum RefundStatus { - REQUESTED("환불 요청됨"), - PROCESSING("환불 처리 중"), - COMPLETED("환불 완료됨"), - REJECTED("환불 거절됨"); - - private final String description; - - RefundStatus(String description) { - this.description = description; - } - - public String getDescription() { - return description; - } -} - -/* -* REQUESTED, // 반품 요청됨 - APPROVED, // 반품 승인됨 - REJECTED, // 반품 거부됨 - RETURNED, // 상품이 반품됨 - REFUNDED, // 환불 완료됨 - CANCELLED, // 반품 요청이 취소됨 - IN_TRANSIT // 반품이 배송 중 - ; -* */ diff --git a/src/main/java/poomasi/domain/order/entity/AbstractOrder.java b/src/main/java/poomasi/domain/order/entity/AbstractOrder.java deleted file mode 100644 index 82a7c4ff..00000000 --- a/src/main/java/poomasi/domain/order/entity/AbstractOrder.java +++ /dev/null @@ -1,33 +0,0 @@ -package poomasi.domain.order.entity; - -import jakarta.persistence.*; -import jdk.jfr.Description; -import jdk.jfr.Timestamp; -import lombok.Getter; -import org.hibernate.annotations.UpdateTimestamp; -import poomasi.domain.member.entity.Member; - -import java.time.LocalDateTime; -import java.util.Date; - -@MappedSuperclass -@Getter -public abstract class AbstractOrder { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @JoinColumn(name = "member_id") - @ManyToOne(fetch = FetchType.LAZY) - private Member member; - - @Column(name = "merchant_uid") - @Description("상품당 결제 id(아임포트 id)") - private String merchantUid = "p" + new Date().getTime(); - - @Column(name = "created_at") - @Timestamp - private LocalDateTime createdAt = LocalDateTime.now(); - -} diff --git a/src/main/java/poomasi/domain/order/entity/Order.java b/src/main/java/poomasi/domain/order/entity/Order.java deleted file mode 100644 index a830bed2..00000000 --- a/src/main/java/poomasi/domain/order/entity/Order.java +++ /dev/null @@ -1,49 +0,0 @@ -package poomasi.domain.order.entity; - - -import jakarta.persistence.*; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; -import java.util.List; - -import static poomasi.domain.order.entity.OrderStatus.PENDING; - -@Entity -@Table(name = "orders") -@Getter -@NoArgsConstructor -public class Order extends AbstractOrder{ - - @Column(name = "order_product_details_id") - @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) - private List orderProductDetails; - - @OneToOne - @JoinColumn(name = "order_details_id") // 여기서 JoinColumn 사용 - private OrderDetails orderDetails; - - @Column(name = "total_amount") - private BigDecimal totalAmount; - - @Enumerated(EnumType.STRING) - private OrderStatus orderStatus = OrderStatus.PENDING; - - public Order(OrderDetails orderDetails) { - this.orderDetails = orderDetails; - } - - public void addOrderDetail(OrderProductDetails orderProductDetails) { - this.orderProductDetails.add(orderProductDetails); - } - public void setOrderStatus(OrderStatus orderStatus) { - this.orderStatus = orderStatus; - } - - public void setTotalAmount(BigDecimal totalAmount) { - this.totalAmount = totalAmount; - } - - -} diff --git a/src/main/java/poomasi/domain/order/entity/OrderDetails.java b/src/main/java/poomasi/domain/order/entity/OrderDetails.java deleted file mode 100644 index 5bb7ed09..00000000 --- a/src/main/java/poomasi/domain/order/entity/OrderDetails.java +++ /dev/null @@ -1,38 +0,0 @@ -package poomasi.domain.order.entity; - -import jakarta.persistence.*; -import jdk.jfr.Description; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Table(name="order_details") -@Getter -@NoArgsConstructor -public class OrderDetails { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(mappedBy = "orderDetails") - private Order order; - - @Column(name = "address") - private String address; - - @Column(name = "address_detail") - private String addressDetail; - - @Description("배송 요청 사항") - @Column(name = "delivery_request", length = 255) - private String deliveryRequest; - - public OrderDetails(String address, String addressDetail, String deliveryRequest) { - this.address = address; - this.addressDetail = addressDetail; - this.deliveryRequest = deliveryRequest; - } - - -} diff --git a/src/main/java/poomasi/domain/order/entity/OrderProductDetails.java b/src/main/java/poomasi/domain/order/entity/OrderProductDetails.java deleted file mode 100644 index 5be2e668..00000000 --- a/src/main/java/poomasi/domain/order/entity/OrderProductDetails.java +++ /dev/null @@ -1,71 +0,0 @@ -package poomasi.domain.order.entity; - - -import jakarta.persistence.*; -import jdk.jfr.Description; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import poomasi.domain.order._refund.entity.Refund; -import poomasi.domain.product.entity.Product; - -import java.io.Serializable; -import java.math.BigDecimal; - -@Entity -@Table(name = "order_product_details") -@Getter -@NoArgsConstructor -public class OrderProductDetails implements Serializable { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "order_product_details_id") - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "product_id") - private Product product; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "order_id") - private Order order; - - /* @OneToOne(fetch = FetchType.LAZY) - private Refund refund;*/ - - @Column(name = "product_description", nullable = true) - private String productDescription; - - @Column(name = "product_name", length = 255) - private String productName; - - @Description("구매 당시 1개당 가격") - private BigDecimal price; - - @Column(name="count") - private Integer count; - - @Description("송장 번호") - @Column(name = "invoice_number") - private String invoiceNumber; - - //private String sellerName; - //private OneToMany Review; - //refund.. - - @Builder - public OrderProductDetails(Product product, Order order, String productDescription, String productName, BigDecimal price, Integer count) { - this.product = product; - this.order = order; - this.productDescription = productDescription; - this.productName = productName; - this.price = price; - this.count = count; - } - - public void setInvoiceNumber(String invoiceNumber) { - this.invoiceNumber = invoiceNumber; - } -} - diff --git a/src/main/java/poomasi/domain/order/entity/OrderStatus.java b/src/main/java/poomasi/domain/order/entity/OrderStatus.java deleted file mode 100644 index 6a3b07a8..00000000 --- a/src/main/java/poomasi/domain/order/entity/OrderStatus.java +++ /dev/null @@ -1,11 +0,0 @@ -package poomasi.domain.order.entity; - -public enum OrderStatus { - PENDING, // 결제 대기 중 - AWAITING_SELLER_CONFIRMATION, // 판매자 확인 대기 중 - READY_FOR_SHIPMENT, // 배송 대기 중 - IN_TRANSIT, // 배송 중 - DELIVERED, // 배송 완료 - ORDER_COMPLETE // 주문 완료 - ; -} \ No newline at end of file diff --git a/src/main/java/poomasi/domain/order/repository/OrderProductDetailsRepository.java b/src/main/java/poomasi/domain/order/repository/OrderProductDetailsRepository.java deleted file mode 100644 index 61432033..00000000 --- a/src/main/java/poomasi/domain/order/repository/OrderProductDetailsRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package poomasi.domain.order.repository; - -import org.springframework.data.jpa.repository.JpaRepository; -import poomasi.domain.order.entity.OrderProductDetails; - -import java.util.List; - -public interface OrderProductDetailsRepository extends JpaRepository { - List findByOrderId(Long orderId); -} diff --git a/src/main/java/poomasi/domain/order/repository/OrderRepository.java b/src/main/java/poomasi/domain/order/repository/OrderRepository.java deleted file mode 100644 index f2476ad0..00000000 --- a/src/main/java/poomasi/domain/order/repository/OrderRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package poomasi.domain.order.repository; - -import org.springframework.data.jpa.repository.JpaRepository; -import poomasi.domain.order.entity.Order; -import poomasi.domain.order.entity.OrderProductDetails; - -import java.util.List; -import java.util.Optional; - -public interface OrderRepository extends JpaRepository { - List findByMemberId(Long memberId); - //List findById(Long id); - Optional findByMerchantUid(String merchantUid); -} From 89441ba15f77cfd6cb283339a6b54811442225f2 Mon Sep 17 00:00:00 2001 From: stopmin Date: Tue, 12 Nov 2024 23:38:42 +0900 Subject: [PATCH 26/26] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=84=EC=8B=9C=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20#149?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../payment/iamportTest/IamportTest.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/test/java/poomasi/domain/payment/iamportTest/IamportTest.java b/src/test/java/poomasi/domain/payment/iamportTest/IamportTest.java index 9d0ac2f4..9510c98f 100644 --- a/src/test/java/poomasi/domain/payment/iamportTest/IamportTest.java +++ b/src/test/java/poomasi/domain/payment/iamportTest/IamportTest.java @@ -40,20 +40,20 @@ public void setUp() { this.iamportClient = new IamportClient(apiKey, secretKey); } - @Test - public void portonePrePaymentRegister_Test() throws IamportResponseException, IOException { - String merchantUid = "poomasi_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); - BigDecimal amount = new BigDecimal("100"); - PrepareData prepareData = new PrepareData(merchantUid, amount); - - // `iamportClient.postPrepare` 모킹 설정 - IamportResponse mockResponse = new IamportResponse<>(); - given(iamportClient.postPrepare(any(PrepareData.class))).willReturn(mockResponse); - - // 테스트 실행 - IamportResponse prepareIamportResponse = iamportClient.postPrepare(prepareData); - System.out.println("Response Code: " + prepareIamportResponse.getCode()); - System.out.println("Response Message: " + prepareIamportResponse.getMessage()); - } +// @Test +// public void portonePrePaymentRegister_Test() throws IamportResponseException, IOException { +// String merchantUid = "poomasi_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); +// BigDecimal amount = new BigDecimal("100"); +// PrepareData prepareData = new PrepareData(merchantUid, amount); +// +// // `iamportClient.postPrepare` 모킹 설정 +// IamportResponse mockResponse = new IamportResponse<>(); +// given(iamportClient.postPrepare(any(PrepareData.class))).willReturn(mockResponse); +// +// // 테스트 실행 +// IamportResponse prepareIamportResponse = iamportClient.postPrepare(prepareData); +// System.out.println("Response Code: " + prepareIamportResponse.getCode()); +// System.out.println("Response Message: " + prepareIamportResponse.getMessage()); +// } }