From 795adde7316828096361a852b8eb96a601315202 Mon Sep 17 00:00:00 2001 From: isExample Date: Tue, 19 Sep 2023 02:11:15 +0900 Subject: [PATCH 01/16] =?UTF-8?q?[Feat]=20User=20=EC=84=9C=EB=B2=84=20WebC?= =?UTF-8?q?lient=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../transaction/config/BaseException.java | 4 +- .../transaction/config/BaseResponse.java | 2 + .../config/BaseResponseStatus.java | 4 +- .../transaction/config/SwaggerConfig.java | 10 ++++ .../transaction/config/WebClientConfig.java | 26 ++++++++++ .../controller/TransactionController.java | 16 +++++-- .../transaction/domain/UserInfo.java | 22 +++++++++ .../transaction/service/UserService.java | 48 +++++++++++++++++++ 9 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 src/main/java/HeyPorori/transaction/config/WebClientConfig.java create mode 100644 src/main/java/HeyPorori/transaction/domain/UserInfo.java create mode 100644 src/main/java/HeyPorori/transaction/service/UserService.java diff --git a/build.gradle b/build.gradle index 929c373..cd99280 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'mysql:mysql-connector-java:8.0.25' implementation 'org.springdoc:springdoc-openapi-ui:1.7.0' + implementation 'org.springframework.boot:spring-boot-starter-webflux' // WebClient compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' diff --git a/src/main/java/HeyPorori/transaction/config/BaseException.java b/src/main/java/HeyPorori/transaction/config/BaseException.java index 104a589..44a7662 100644 --- a/src/main/java/HeyPorori/transaction/config/BaseException.java +++ b/src/main/java/HeyPorori/transaction/config/BaseException.java @@ -2,11 +2,13 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @AllArgsConstructor -public class BaseException extends Exception { +@NoArgsConstructor +public class BaseException extends RuntimeException { private BaseResponseStatus status; } \ No newline at end of file diff --git a/src/main/java/HeyPorori/transaction/config/BaseResponse.java b/src/main/java/HeyPorori/transaction/config/BaseResponse.java index 109f396..91a9262 100644 --- a/src/main/java/HeyPorori/transaction/config/BaseResponse.java +++ b/src/main/java/HeyPorori/transaction/config/BaseResponse.java @@ -4,11 +4,13 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import static HeyPorori.transaction.config.BaseResponseStatus.SUCCESS; @Getter @AllArgsConstructor +@NoArgsConstructor @JsonPropertyOrder({"statusCode", "message", "data"}) public class BaseResponse { private String message; diff --git a/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java b/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java index c40cc08..08f0ce5 100644 --- a/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java +++ b/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java @@ -5,7 +5,9 @@ @Getter public enum BaseResponseStatus { /* 요청 성공 */ - SUCCESS(true, 1000, "요청에 성공하였습니다.") + SUCCESS(true, 1000, "요청에 성공하였습니다."), + USER_INVALID_RESPONSE(false, 1050, "User 서비스로부터 올바른 응답을 받지 못하였습니다."), + INVALID_JWT(false, 1051, "잘못된 JWT 토큰입니다.") ; private final boolean isSuccess; diff --git a/src/main/java/HeyPorori/transaction/config/SwaggerConfig.java b/src/main/java/HeyPorori/transaction/config/SwaggerConfig.java index 1b6dc61..d23e2e5 100644 --- a/src/main/java/HeyPorori/transaction/config/SwaggerConfig.java +++ b/src/main/java/HeyPorori/transaction/config/SwaggerConfig.java @@ -1,11 +1,21 @@ package HeyPorori.transaction.config; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.security.SecurityScheme; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration +@SecurityScheme( + type = SecuritySchemeType.APIKEY, in = SecuritySchemeIn.HEADER, + name = "Authorization", description = "Authorization" +) +@OpenAPIDefinition(security = { @SecurityRequirement(name = "Authorization") }) public class SwaggerConfig { @Bean public OpenAPI customOpenAPI() { diff --git a/src/main/java/HeyPorori/transaction/config/WebClientConfig.java b/src/main/java/HeyPorori/transaction/config/WebClientConfig.java new file mode 100644 index 0000000..cfe40c7 --- /dev/null +++ b/src/main/java/HeyPorori/transaction/config/WebClientConfig.java @@ -0,0 +1,26 @@ +package HeyPorori.transaction.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.reactive.ReactorResourceFactory; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +public class WebClientConfig { + @Value("${service.user}") + private String userUrl; + @Bean + public ReactorResourceFactory reactorResourceFactory(){ + ReactorResourceFactory factory = new ReactorResourceFactory(); + factory.setUseGlobalResources(false); + return factory; + } + + @Bean + public WebClient webClient(){ + return WebClient.builder() + .baseUrl(userUrl) + .build(); + } +} diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index 3fb02af..803316a 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -3,6 +3,7 @@ import HeyPorori.transaction.config.BaseException; import HeyPorori.transaction.config.BaseResponse; import HeyPorori.transaction.service.TransactionService; +import HeyPorori.transaction.service.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -10,9 +11,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RequiredArgsConstructor @Tag(name = "중고거래", description = "중고거래 관련 API 입니다.") @@ -20,11 +19,18 @@ @RequestMapping("/api/transactions") public class TransactionController { private final TransactionService transactionService; + private final UserService userService; @Operation(summary = "Swagger UI 테스트용 메서드", description = "프로젝트 초기 Swagger UI 정상작동을 확인하기 위한 메서드입니다.") @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) @GetMapping("/test") - public BaseResponse testSwagger() { - return new BaseResponse<>("테스트 성공"); + public BaseResponse testSwagger() { return new BaseResponse<>("테스트 성공"); } + + @Operation(summary = "User 서버 테스트용 메서드", description = "User 서버와의 통신이 정상작동하는지 확인하기 위한 메서드입니다.") + @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) + @PostMapping("/testUser") + public BaseResponse testUserService(@RequestHeader("Authorization") String token) { + userService.sendTestJwtRequest(token); + return new BaseResponse<>(userService.getUserId(token)); } } diff --git a/src/main/java/HeyPorori/transaction/domain/UserInfo.java b/src/main/java/HeyPorori/transaction/domain/UserInfo.java new file mode 100644 index 0000000..51a0fac --- /dev/null +++ b/src/main/java/HeyPorori/transaction/domain/UserInfo.java @@ -0,0 +1,22 @@ +package HeyPorori.transaction.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserInfo { + private Long userId; + private String name; + private String nickName; + private String phoneNumber; + private boolean gender; + private String address; + private String backgroundColor; + private String email; + private String imageUrl; +} diff --git a/src/main/java/HeyPorori/transaction/service/UserService.java b/src/main/java/HeyPorori/transaction/service/UserService.java new file mode 100644 index 0000000..025eaa7 --- /dev/null +++ b/src/main/java/HeyPorori/transaction/service/UserService.java @@ -0,0 +1,48 @@ +package HeyPorori.transaction.service; + +import HeyPorori.transaction.config.BaseException; +import HeyPorori.transaction.config.BaseResponse; +import HeyPorori.transaction.config.BaseResponseStatus; +import HeyPorori.transaction.domain.UserInfo; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; + +@Slf4j +@Service +@RequiredArgsConstructor +public class UserService { + private final WebClient webClient; + private static final String LOG_FORMAT = "Method : {}"; + + public Long getUserId(String token) { + return postTokenRequest(token).getUserId(); + } + + private UserInfo postTokenRequest(String token) { + return webClient.get() + .uri("/token/me") + .header("Authorization", token) + .retrieve() + .bodyToMono((new ParameterizedTypeReference>() { + })) + .map(BaseResponse::getData) + .block(); + } + + public void sendTestJwtRequest(String token) { + try { + webClient.post() + .uri("/test/jwt") + .header("Authorization", token) + .retrieve() + .toBodilessEntity() + .block(); + } catch (Exception e) { + log.warn(LOG_FORMAT, "sendTestJwtRequest"); + throw new BaseException(BaseResponseStatus.INVALID_JWT); + } + } +} From 25f1fd2857b397257c054559777012d00d5b52f3 Mon Sep 17 00:00:00 2001 From: isExample Date: Wed, 20 Sep 2023 01:52:36 +0900 Subject: [PATCH 02/16] =?UTF-8?q?[Feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20API(=EC=82=AC=EC=A7=84=20=EC=B2=A8?= =?UTF-8?q?=EB=B6=80=20=EC=A0=9C=EC=99=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../transaction/TransactionApplication.java | 2 ++ .../config/BaseResponseStatus.java | 6 ++++- .../controller/TransactionController.java | 14 +++++++++++ .../transaction/domain/Category.java | 12 ++++++++++ .../transaction/domain/Transaction.java | 16 ++++++++++++- .../HeyPorori/transaction/dto/PostReq.java | 23 +++++++++++++++++++ .../service/TransactionService.java | 12 ++++++++++ 8 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 src/main/java/HeyPorori/transaction/dto/PostReq.java diff --git a/build.gradle b/build.gradle index cd99280..44b2615 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,7 @@ dependencies { implementation 'mysql:mysql-connector-java:8.0.25' implementation 'org.springdoc:springdoc-openapi-ui:1.7.0' implementation 'org.springframework.boot:spring-boot-starter-webflux' // WebClient + implementation 'org.springframework.boot:spring-boot-starter-validation' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' diff --git a/src/main/java/HeyPorori/transaction/TransactionApplication.java b/src/main/java/HeyPorori/transaction/TransactionApplication.java index 72b163c..fc9552d 100644 --- a/src/main/java/HeyPorori/transaction/TransactionApplication.java +++ b/src/main/java/HeyPorori/transaction/TransactionApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @SpringBootApplication +@EnableJpaAuditing public class TransactionApplication { public static void main(String[] args) { diff --git a/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java b/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java index 08f0ce5..3a5d38e 100644 --- a/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java +++ b/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java @@ -6,8 +6,12 @@ public enum BaseResponseStatus { /* 요청 성공 */ SUCCESS(true, 1000, "요청에 성공하였습니다."), + + /* 요청 실패 */ USER_INVALID_RESPONSE(false, 1050, "User 서비스로부터 올바른 응답을 받지 못하였습니다."), - INVALID_JWT(false, 1051, "잘못된 JWT 토큰입니다.") + INVALID_JWT(false, 1051, "잘못된 JWT 토큰입니다."), + INVALID_CATEGORY(false, 3001, "유효하지 않은 카테고리입니다.") + ; private final boolean isSuccess; diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index 803316a..c57195e 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -2,6 +2,8 @@ import HeyPorori.transaction.config.BaseException; import HeyPorori.transaction.config.BaseResponse; +import HeyPorori.transaction.config.BaseResponseStatus; +import HeyPorori.transaction.dto.PostReq; import HeyPorori.transaction.service.TransactionService; import HeyPorori.transaction.service.UserService; import io.swagger.v3.oas.annotations.Operation; @@ -13,6 +15,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import javax.validation.Valid; + @RequiredArgsConstructor @Tag(name = "중고거래", description = "중고거래 관련 API 입니다.") @RestController @@ -21,6 +25,7 @@ public class TransactionController { private final TransactionService transactionService; private final UserService userService; + // 테스트용 APIs @Operation(summary = "Swagger UI 테스트용 메서드", description = "프로젝트 초기 Swagger UI 정상작동을 확인하기 위한 메서드입니다.") @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) @GetMapping("/test") @@ -33,4 +38,13 @@ public BaseResponse testUserService(@RequestHeader("Authorization") String userService.sendTestJwtRequest(token); return new BaseResponse<>(userService.getUserId(token)); } + + // 실사용 APIs + @Operation(summary = "중고거래 게시글 작성 API", description = "중고거래 서비스의 거래 게시글을 작성하기 위한 API입니다.") + @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) + @PostMapping("/post") + public BaseResponse createPost(@RequestHeader("Authorization") String token, @RequestBody @Valid PostReq postReq) { + transactionService.createPost(token, postReq); + return new BaseResponse<>(BaseResponseStatus.SUCCESS); + } } diff --git a/src/main/java/HeyPorori/transaction/domain/Category.java b/src/main/java/HeyPorori/transaction/domain/Category.java index 7bb5bcc..6b9b327 100644 --- a/src/main/java/HeyPorori/transaction/domain/Category.java +++ b/src/main/java/HeyPorori/transaction/domain/Category.java @@ -1,7 +1,13 @@ package HeyPorori.transaction.domain; +import HeyPorori.transaction.config.BaseException; +import HeyPorori.transaction.config.BaseResponseStatus; +import com.fasterxml.jackson.annotation.JsonCreator; import lombok.Getter; +import java.util.Arrays; +import java.util.stream.Stream; + @Getter public enum Category { ELECTRONICS("전자제품", "스마트폰, 컴퓨터, 태블릿, TV, 오디오 기기 등"), @@ -20,4 +26,10 @@ public enum Category { this.name = name; this.description = description; } + + public static Category parsing(String inputValue) { + return Arrays.stream(Category.values()) + .filter(r -> r.name.equals(inputValue)) + .findAny().orElse(null); + } } \ No newline at end of file diff --git a/src/main/java/HeyPorori/transaction/domain/Transaction.java b/src/main/java/HeyPorori/transaction/domain/Transaction.java index df465e7..dfe7940 100644 --- a/src/main/java/HeyPorori/transaction/domain/Transaction.java +++ b/src/main/java/HeyPorori/transaction/domain/Transaction.java @@ -1,6 +1,7 @@ package HeyPorori.transaction.domain; import HeyPorori.transaction.config.BaseTimeEntity; +import HeyPorori.transaction.dto.PostReq; import lombok.*; import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.DynamicInsert; @@ -44,7 +45,7 @@ public class Transaction extends BaseTimeEntity { @Column(nullable = false) private Double longitude; - @Column(nullable = false) + @Column(nullable = true) private Category category; @ColumnDefault("'ACTIVE'") @@ -69,6 +70,19 @@ public Transaction(Long userId, String title, String content, int recommend, Str this.status = status; } + public static Transaction toEntity(PostReq postReq, Long userId){ + return Transaction.builder() + .userId(userId) + .title(postReq.getTitle()) + .content(postReq.getContent()) + .recommend(0) + .address("필동") + .latitude(0.0) + .longitude(0.0) + .category(Category.parsing(postReq.getCategory())) + .build(); + } + public void changeStatus(String status) { this.status = status; } diff --git a/src/main/java/HeyPorori/transaction/dto/PostReq.java b/src/main/java/HeyPorori/transaction/dto/PostReq.java new file mode 100644 index 0000000..41d8c94 --- /dev/null +++ b/src/main/java/HeyPorori/transaction/dto/PostReq.java @@ -0,0 +1,23 @@ +package HeyPorori.transaction.dto; + +import HeyPorori.transaction.domain.Category; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class PostReq { + @Size(min = 1, max = 20, message = "거래 게시글 제목의 길이는 1 이상 20 이하입니다.") + private String title; + @Size(min = 1, max = 200, message = "거래 게시글 내용의 길이는 1 이상 200 이하입니다.") + private String content; + @Pattern(regexp = "^(전자제품|의류 및 액세서리|가구 및 가정용품|스포츠 및 레저|자동차 및 오토바이|도서 및 음악|아기 및 어린이 용품|기타)$", message = "유효하지 않은 카테고리입니다.") + private String category; +} diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index c553bad..1737bf0 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -1,10 +1,22 @@ package HeyPorori.transaction.service; +import HeyPorori.transaction.domain.Transaction; +import HeyPorori.transaction.dto.PostReq; +import HeyPorori.transaction.repository.TransactionRepository; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import javax.transaction.Transactional; @Service @Transactional +@RequiredArgsConstructor public class TransactionService { + private final TransactionRepository transactionRepository; + private final UserService userService; + + public void createPost(String token, PostReq postReq) { + userService.sendTestJwtRequest(token); + transactionRepository.save(Transaction.toEntity(postReq, userService.getUserId(token))); + } } From d3d35ff9a62933a7e7c9591825d7fde2a7a24e77 Mon Sep 17 00:00:00 2001 From: isExample Date: Sat, 23 Sep 2023 00:11:36 +0900 Subject: [PATCH 03/16] =?UTF-8?q?[Feat]=20AWS=20S3=20Pre-Signed=20Url=20?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../transaction/TransactionApplication.java | 4 +- .../transaction/config/AmazonS3Config.java | 36 ++++++++++++ .../controller/TransactionController.java | 11 +++- .../transaction/dto/PreSignedUrlRes.java | 14 +++++ .../transaction/service/AmazonS3Service.java | 55 +++++++++++++++++++ 6 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 src/main/java/HeyPorori/transaction/config/AmazonS3Config.java create mode 100644 src/main/java/HeyPorori/transaction/dto/PreSignedUrlRes.java create mode 100644 src/main/java/HeyPorori/transaction/service/AmazonS3Service.java diff --git a/build.gradle b/build.gradle index 44b2615..3a61b70 100644 --- a/build.gradle +++ b/build.gradle @@ -28,6 +28,7 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-ui:1.7.0' implementation 'org.springframework.boot:spring-boot-starter-webflux' // WebClient implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' // S3 compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' diff --git a/src/main/java/HeyPorori/transaction/TransactionApplication.java b/src/main/java/HeyPorori/transaction/TransactionApplication.java index fc9552d..c5c0269 100644 --- a/src/main/java/HeyPorori/transaction/TransactionApplication.java +++ b/src/main/java/HeyPorori/transaction/TransactionApplication.java @@ -7,7 +7,9 @@ @SpringBootApplication @EnableJpaAuditing public class TransactionApplication { - + static { + System.setProperty("com.amazonaws.sdk.disableEc2Metadata", "true"); // S3 예외발생 방지 + } public static void main(String[] args) { SpringApplication.run(TransactionApplication.class, args); } diff --git a/src/main/java/HeyPorori/transaction/config/AmazonS3Config.java b/src/main/java/HeyPorori/transaction/config/AmazonS3Config.java new file mode 100644 index 0000000..8a767f4 --- /dev/null +++ b/src/main/java/HeyPorori/transaction/config/AmazonS3Config.java @@ -0,0 +1,36 @@ +package HeyPorori.transaction.config; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +@Configuration +public class AmazonS3Config { + @Value("${cloud.aws.credentials.access-key}") + private String accessKey; + + @Value("${cloud.aws.credentials.secret-key}") + private String secretKey; + + @Value("${cloud.aws.region.static}") + private String region; + + @Bean + @Primary + public BasicAWSCredentials awsCredentialsProvider(){ + return new BasicAWSCredentials(accessKey, secretKey); + } + + @Bean + public AmazonS3 amazonS3Client() { + return AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentialsProvider())) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index c57195e..e4edcb4 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -4,13 +4,14 @@ import HeyPorori.transaction.config.BaseResponse; import HeyPorori.transaction.config.BaseResponseStatus; import HeyPorori.transaction.dto.PostReq; +import HeyPorori.transaction.dto.PreSignedUrlRes; +import HeyPorori.transaction.service.AmazonS3Service; import HeyPorori.transaction.service.TransactionService; import HeyPorori.transaction.service.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -24,6 +25,7 @@ public class TransactionController { private final TransactionService transactionService; private final UserService userService; + private final AmazonS3Service amazonS3Service; // 테스트용 APIs @Operation(summary = "Swagger UI 테스트용 메서드", description = "프로젝트 초기 Swagger UI 정상작동을 확인하기 위한 메서드입니다.") @@ -47,4 +49,11 @@ public BaseResponse createPost(@RequestHeader("Authorization transactionService.createPost(token, postReq); return new BaseResponse<>(BaseResponseStatus.SUCCESS); } + + @Operation(summary = "Pre-Signed Url 발급 API", description = "AWS S3 이미지 업로드 권한을 요청하기 위한 API입니다.") + @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) + @GetMapping("/url") + public BaseResponse getPreSignedUrl(@RequestHeader("Authorization") String token) throws BaseException { + return new BaseResponse<>(amazonS3Service.getPreSignedUrl()); + } } diff --git a/src/main/java/HeyPorori/transaction/dto/PreSignedUrlRes.java b/src/main/java/HeyPorori/transaction/dto/PreSignedUrlRes.java new file mode 100644 index 0000000..7b2fad2 --- /dev/null +++ b/src/main/java/HeyPorori/transaction/dto/PreSignedUrlRes.java @@ -0,0 +1,14 @@ +package HeyPorori.transaction.dto; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class PreSignedUrlRes { + private String url; + + @Builder + public PreSignedUrlRes(String url) { + this.url = url; + } +} diff --git a/src/main/java/HeyPorori/transaction/service/AmazonS3Service.java b/src/main/java/HeyPorori/transaction/service/AmazonS3Service.java new file mode 100644 index 0000000..0aef55b --- /dev/null +++ b/src/main/java/HeyPorori/transaction/service/AmazonS3Service.java @@ -0,0 +1,55 @@ +package HeyPorori.transaction.service; + +import HeyPorori.transaction.dto.PreSignedUrlRes; +import com.amazonaws.HttpMethod; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.Headers; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.Date; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +@Transactional +public class AmazonS3Service { + private final AmazonS3 amazonS3; + + @Value("${cloud.aws.s3.bucket}") + private String bucket; + + public PreSignedUrlRes getPreSignedUrl(){ + String uuid = UUID.randomUUID().toString(); + String objectKey = "transactions/"+uuid; + + GeneratePresignedUrlRequest request = generatePresignedUrlRequest(bucket, objectKey); + PreSignedUrlRes response = PreSignedUrlRes.builder() + .url(amazonS3.generatePresignedUrl(request).toString()) + .build(); + return response; + } + + private GeneratePresignedUrlRequest generatePresignedUrlRequest(String bucket, String imageName){ + Date expiration = new Date(); + long expTimeMillis = expiration.getTime(); + expTimeMillis += 1000 * 60 * 5; // 5분 + expiration.setTime(expTimeMillis); + + //Pre-Signed Url request 생성 + GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, imageName) + .withMethod(HttpMethod.PUT) + .withExpiration(expiration); + + //request 파라미터 추가 + request.addRequestParameter( + Headers.S3_CANNED_ACL, + CannedAccessControlList.PublicRead.toString()); + + return request; + } +} \ No newline at end of file From e042b1070655a185b6cda1d7c51c1d217b024342 Mon Sep 17 00:00:00 2001 From: isExample Date: Sat, 23 Sep 2023 00:51:49 +0900 Subject: [PATCH 04/16] =?UTF-8?q?[Feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20API=20-=20=EC=82=AC=EC=A7=84=20=EC=B2=A8?= =?UTF-8?q?=EB=B6=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transaction/domain/TransactionAttach.java | 8 ++++++ .../HeyPorori/transaction/dto/PostReq.java | 3 +++ .../service/TransactionAttachService.java | 26 +++++++++++++++++++ .../service/TransactionService.java | 5 +++- 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/main/java/HeyPorori/transaction/service/TransactionAttachService.java diff --git a/src/main/java/HeyPorori/transaction/domain/TransactionAttach.java b/src/main/java/HeyPorori/transaction/domain/TransactionAttach.java index 75f7490..da4ef06 100644 --- a/src/main/java/HeyPorori/transaction/domain/TransactionAttach.java +++ b/src/main/java/HeyPorori/transaction/domain/TransactionAttach.java @@ -1,6 +1,7 @@ package HeyPorori.transaction.domain; import HeyPorori.transaction.config.BaseTimeEntity; +import HeyPorori.transaction.dto.PostReq; import lombok.*; import org.hibernate.annotations.DynamicUpdate; @@ -30,4 +31,11 @@ public TransactionAttach(Transaction transactionId, String imageUrl){ this.transactionId = transactionId; this.imageUrl = imageUrl; } + + public static TransactionAttach toEntity(Transaction transaction, String imageUrl){ + return TransactionAttach.builder() + .transactionId(transaction) + .imageUrl(imageUrl) + .build(); + } } diff --git a/src/main/java/HeyPorori/transaction/dto/PostReq.java b/src/main/java/HeyPorori/transaction/dto/PostReq.java index 41d8c94..e7ea6c9 100644 --- a/src/main/java/HeyPorori/transaction/dto/PostReq.java +++ b/src/main/java/HeyPorori/transaction/dto/PostReq.java @@ -9,6 +9,7 @@ import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; +import java.util.List; @Getter @NoArgsConstructor @@ -20,4 +21,6 @@ public class PostReq { private String content; @Pattern(regexp = "^(전자제품|의류 및 액세서리|가구 및 가정용품|스포츠 및 레저|자동차 및 오토바이|도서 및 음악|아기 및 어린이 용품|기타)$", message = "유효하지 않은 카테고리입니다.") private String category; + @Size(max = 3, message = "거래 게시글에 첨부할 수 있는 사진은 3장 이하입니다.") + private List imageNameList; } diff --git a/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java b/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java new file mode 100644 index 0000000..9c0dbee --- /dev/null +++ b/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java @@ -0,0 +1,26 @@ +package HeyPorori.transaction.service; + +import HeyPorori.transaction.domain.Transaction; +import HeyPorori.transaction.domain.TransactionAttach; +import HeyPorori.transaction.repository.TransactionAttachRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +public class TransactionAttachService { + private final TransactionAttachRepository transactionAttachRepository; + + public List savePostAttach(Transaction transaction, List imageNameList){ + List TransactionAttachList = new ArrayList<>(); + for(String imageName: imageNameList){ + TransactionAttachList.add(TransactionAttach.toEntity(transaction, imageName)); + } + return TransactionAttachList; + } +} diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index 1737bf0..4358312 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -14,9 +14,12 @@ public class TransactionService { private final TransactionRepository transactionRepository; private final UserService userService; + private final TransactionAttachService transactionAttachService; public void createPost(String token, PostReq postReq) { userService.sendTestJwtRequest(token); - transactionRepository.save(Transaction.toEntity(postReq, userService.getUserId(token))); + Transaction txn = Transaction.toEntity(postReq, userService.getUserId(token)); + txn.setAttachList(transactionAttachService.savePostAttach(txn, postReq.getImageNameList())); + transactionRepository.save(txn); } } From dd6610455af0b3a18dc52bd891e23652707bd46c Mon Sep 17 00:00:00 2001 From: isExample Date: Sat, 23 Sep 2023 01:31:28 +0900 Subject: [PATCH 05/16] =?UTF-8?q?[Fix]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20Cat?= =?UTF-8?q?egory=20=EC=A0=80=EC=9E=A5=20=ED=98=95=ED=83=9C=20idx=20->=20st?= =?UTF-8?q?ring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/HeyPorori/transaction/domain/Transaction.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/HeyPorori/transaction/domain/Transaction.java b/src/main/java/HeyPorori/transaction/domain/Transaction.java index dfe7940..3017610 100644 --- a/src/main/java/HeyPorori/transaction/domain/Transaction.java +++ b/src/main/java/HeyPorori/transaction/domain/Transaction.java @@ -45,6 +45,7 @@ public class Transaction extends BaseTimeEntity { @Column(nullable = false) private Double longitude; + @Enumerated(value = EnumType.STRING) @Column(nullable = true) private Category category; From e61cfa8e1dbd803a3147971a9c29e72896123167 Mon Sep 17 00:00:00 2001 From: isExample Date: Sat, 23 Sep 2023 02:27:50 +0900 Subject: [PATCH 06/16] =?UTF-8?q?[Feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TransactionController.java | 9 ++++++ .../HeyPorori/transaction/dto/PostRes.java | 32 +++++++++++++++++++ .../repository/TransactionRepository.java | 6 ++++ .../service/TransactionAttachService.java | 9 ++++++ .../service/TransactionService.java | 21 ++++++++++++ 5 files changed, 77 insertions(+) create mode 100644 src/main/java/HeyPorori/transaction/dto/PostRes.java diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index e4edcb4..454365f 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -4,6 +4,7 @@ import HeyPorori.transaction.config.BaseResponse; import HeyPorori.transaction.config.BaseResponseStatus; import HeyPorori.transaction.dto.PostReq; +import HeyPorori.transaction.dto.PostRes; import HeyPorori.transaction.dto.PreSignedUrlRes; import HeyPorori.transaction.service.AmazonS3Service; import HeyPorori.transaction.service.TransactionService; @@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.*; import javax.validation.Valid; +import java.util.List; @RequiredArgsConstructor @Tag(name = "중고거래", description = "중고거래 관련 API 입니다.") @@ -56,4 +58,11 @@ public BaseResponse createPost(@RequestHeader("Authorization public BaseResponse getPreSignedUrl(@RequestHeader("Authorization") String token) throws BaseException { return new BaseResponse<>(amazonS3Service.getPreSignedUrl()); } + + @Operation(summary = "중고거래 게시글 목록 조회 API", description = "중고거래 서비스의 거래 게시글 목록을 조회하기 위한 API입니다.") + @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) + @GetMapping("/post") + public BaseResponse> getAllPostByCategory(String category) throws BaseException { + return new BaseResponse<>(transactionService.findAllPostByCategory(category)); + } } diff --git a/src/main/java/HeyPorori/transaction/dto/PostRes.java b/src/main/java/HeyPorori/transaction/dto/PostRes.java new file mode 100644 index 0000000..80e8641 --- /dev/null +++ b/src/main/java/HeyPorori/transaction/dto/PostRes.java @@ -0,0 +1,32 @@ +package HeyPorori.transaction.dto; + +import HeyPorori.transaction.domain.Transaction; +import HeyPorori.transaction.domain.TransactionAttach; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import java.util.List; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PostRes { + private String title; + private String imageName; + private String address; + private int recommend; + + public static PostRes toDto(Transaction transaction, String imageName){ + return PostRes.builder() + .title(transaction.getTitle()) + .imageName(imageName) + .address(transaction.getAddress()) + .recommend(transaction.getRecommendList().size()) + .build(); + } +} diff --git a/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java b/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java index 72eb3ae..9d8a56e 100644 --- a/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java +++ b/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java @@ -1,9 +1,15 @@ package HeyPorori.transaction.repository; +import HeyPorori.transaction.domain.Category; import HeyPorori.transaction.domain.Transaction; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Optional; + @Repository public interface TransactionRepository extends JpaRepository { + List findByStatus(String status); + List findByCategoryAndStatus(Category category, String status); } diff --git a/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java b/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java index 9c0dbee..3e661a6 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java @@ -23,4 +23,13 @@ public List savePostAttach(Transaction transaction, List attachList = transaction.getAttachList(); + if(attachList.size() == 0){ + return ""; + } else{ + return attachList.get(0).getImageUrl(); + } + } } diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index 4358312..03168e3 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -1,12 +1,16 @@ package HeyPorori.transaction.service; +import HeyPorori.transaction.domain.Category; import HeyPorori.transaction.domain.Transaction; import HeyPorori.transaction.dto.PostReq; +import HeyPorori.transaction.dto.PostRes; import HeyPorori.transaction.repository.TransactionRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; @Service @Transactional @@ -22,4 +26,21 @@ public void createPost(String token, PostReq postReq) { txn.setAttachList(transactionAttachService.savePostAttach(txn, postReq.getImageNameList())); transactionRepository.save(txn); } + + public List findAllPostByCategory(String category){ + List txnList = new ArrayList<>(); + if(category.equals("NONE")){ + txnList = transactionRepository.findByStatus("ACTIVE"); + } else{ + txnList = transactionRepository.findByCategoryAndStatus(Category.parsing(category), "ACTIVE"); + } + + List postResList = new ArrayList<>(); + for(Transaction txn: txnList){ + PostRes postRes = PostRes.toDto(txn, transactionAttachService.getFirstImageName(txn)); + postResList.add(postRes); + } + + return postResList; + } } From 5d6e972729bcf3148b0f670a996f1413d6687bfa Mon Sep 17 00:00:00 2001 From: isExample Date: Sat, 23 Sep 2023 03:24:44 +0900 Subject: [PATCH 07/16] =?UTF-8?q?[Refactor]=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20Request=20&=20Response=20DTO=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=ED=95=98=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TransactionController.java | 8 ++++---- .../HeyPorori/transaction/domain/Transaction.java | 4 ++-- .../transaction/domain/TransactionAttach.java | 1 - .../dto/{PostReq.java => CreatePostReq.java} | 5 +---- .../dto/{PostRes.java => GetPostsRes.java} | 11 +++-------- .../transaction/service/TransactionService.java | 12 ++++++------ 6 files changed, 16 insertions(+), 25 deletions(-) rename src/main/java/HeyPorori/transaction/dto/{PostReq.java => CreatePostReq.java} (85%) rename src/main/java/HeyPorori/transaction/dto/{PostRes.java => GetPostsRes.java} (66%) diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index 454365f..847548d 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -3,8 +3,8 @@ import HeyPorori.transaction.config.BaseException; import HeyPorori.transaction.config.BaseResponse; import HeyPorori.transaction.config.BaseResponseStatus; -import HeyPorori.transaction.dto.PostReq; -import HeyPorori.transaction.dto.PostRes; +import HeyPorori.transaction.dto.CreatePostReq; +import HeyPorori.transaction.dto.GetPostsRes; import HeyPorori.transaction.dto.PreSignedUrlRes; import HeyPorori.transaction.service.AmazonS3Service; import HeyPorori.transaction.service.TransactionService; @@ -47,7 +47,7 @@ public BaseResponse testUserService(@RequestHeader("Authorization") String @Operation(summary = "중고거래 게시글 작성 API", description = "중고거래 서비스의 거래 게시글을 작성하기 위한 API입니다.") @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) @PostMapping("/post") - public BaseResponse createPost(@RequestHeader("Authorization") String token, @RequestBody @Valid PostReq postReq) { + public BaseResponse createPost(@RequestHeader("Authorization") String token, @RequestBody @Valid CreatePostReq postReq) { transactionService.createPost(token, postReq); return new BaseResponse<>(BaseResponseStatus.SUCCESS); } @@ -62,7 +62,7 @@ public BaseResponse getPreSignedUrl(@RequestHeader("Authorizati @Operation(summary = "중고거래 게시글 목록 조회 API", description = "중고거래 서비스의 거래 게시글 목록을 조회하기 위한 API입니다.") @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) @GetMapping("/post") - public BaseResponse> getAllPostByCategory(String category) throws BaseException { + public BaseResponse> getAllPostByCategory(String category) throws BaseException { return new BaseResponse<>(transactionService.findAllPostByCategory(category)); } } diff --git a/src/main/java/HeyPorori/transaction/domain/Transaction.java b/src/main/java/HeyPorori/transaction/domain/Transaction.java index 3017610..c20e918 100644 --- a/src/main/java/HeyPorori/transaction/domain/Transaction.java +++ b/src/main/java/HeyPorori/transaction/domain/Transaction.java @@ -1,7 +1,7 @@ package HeyPorori.transaction.domain; import HeyPorori.transaction.config.BaseTimeEntity; -import HeyPorori.transaction.dto.PostReq; +import HeyPorori.transaction.dto.CreatePostReq; import lombok.*; import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.DynamicInsert; @@ -71,7 +71,7 @@ public Transaction(Long userId, String title, String content, int recommend, Str this.status = status; } - public static Transaction toEntity(PostReq postReq, Long userId){ + public static Transaction toEntity(CreatePostReq postReq, Long userId){ return Transaction.builder() .userId(userId) .title(postReq.getTitle()) diff --git a/src/main/java/HeyPorori/transaction/domain/TransactionAttach.java b/src/main/java/HeyPorori/transaction/domain/TransactionAttach.java index da4ef06..852efe2 100644 --- a/src/main/java/HeyPorori/transaction/domain/TransactionAttach.java +++ b/src/main/java/HeyPorori/transaction/domain/TransactionAttach.java @@ -1,7 +1,6 @@ package HeyPorori.transaction.domain; import HeyPorori.transaction.config.BaseTimeEntity; -import HeyPorori.transaction.dto.PostReq; import lombok.*; import org.hibernate.annotations.DynamicUpdate; diff --git a/src/main/java/HeyPorori/transaction/dto/PostReq.java b/src/main/java/HeyPorori/transaction/dto/CreatePostReq.java similarity index 85% rename from src/main/java/HeyPorori/transaction/dto/PostReq.java rename to src/main/java/HeyPorori/transaction/dto/CreatePostReq.java index e7ea6c9..ca5fd9b 100644 --- a/src/main/java/HeyPorori/transaction/dto/PostReq.java +++ b/src/main/java/HeyPorori/transaction/dto/CreatePostReq.java @@ -1,12 +1,9 @@ package HeyPorori.transaction.dto; -import HeyPorori.transaction.domain.Category; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import java.util.List; @@ -14,7 +11,7 @@ @Getter @NoArgsConstructor @AllArgsConstructor -public class PostReq { +public class CreatePostReq { @Size(min = 1, max = 20, message = "거래 게시글 제목의 길이는 1 이상 20 이하입니다.") private String title; @Size(min = 1, max = 200, message = "거래 게시글 내용의 길이는 1 이상 200 이하입니다.") diff --git a/src/main/java/HeyPorori/transaction/dto/PostRes.java b/src/main/java/HeyPorori/transaction/dto/GetPostsRes.java similarity index 66% rename from src/main/java/HeyPorori/transaction/dto/PostRes.java rename to src/main/java/HeyPorori/transaction/dto/GetPostsRes.java index 80e8641..f6b59a1 100644 --- a/src/main/java/HeyPorori/transaction/dto/PostRes.java +++ b/src/main/java/HeyPorori/transaction/dto/GetPostsRes.java @@ -1,28 +1,23 @@ package HeyPorori.transaction.dto; import HeyPorori.transaction.domain.Transaction; -import HeyPorori.transaction.domain.TransactionAttach; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.Pattern; -import javax.validation.constraints.Size; -import java.util.List; - @Getter @Builder @NoArgsConstructor @AllArgsConstructor -public class PostRes { +public class GetPostsRes { private String title; private String imageName; private String address; private int recommend; - public static PostRes toDto(Transaction transaction, String imageName){ - return PostRes.builder() + public static GetPostsRes toDto(Transaction transaction, String imageName){ + return GetPostsRes.builder() .title(transaction.getTitle()) .imageName(imageName) .address(transaction.getAddress()) diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index 03168e3..3e393f0 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -2,8 +2,8 @@ import HeyPorori.transaction.domain.Category; import HeyPorori.transaction.domain.Transaction; -import HeyPorori.transaction.dto.PostReq; -import HeyPorori.transaction.dto.PostRes; +import HeyPorori.transaction.dto.CreatePostReq; +import HeyPorori.transaction.dto.GetPostsRes; import HeyPorori.transaction.repository.TransactionRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,14 +20,14 @@ public class TransactionService { private final UserService userService; private final TransactionAttachService transactionAttachService; - public void createPost(String token, PostReq postReq) { + public void createPost(String token, CreatePostReq postReq) { userService.sendTestJwtRequest(token); Transaction txn = Transaction.toEntity(postReq, userService.getUserId(token)); txn.setAttachList(transactionAttachService.savePostAttach(txn, postReq.getImageNameList())); transactionRepository.save(txn); } - public List findAllPostByCategory(String category){ + public List findAllPostByCategory(String category){ List txnList = new ArrayList<>(); if(category.equals("NONE")){ txnList = transactionRepository.findByStatus("ACTIVE"); @@ -35,9 +35,9 @@ public List findAllPostByCategory(String category){ txnList = transactionRepository.findByCategoryAndStatus(Category.parsing(category), "ACTIVE"); } - List postResList = new ArrayList<>(); + List postResList = new ArrayList<>(); for(Transaction txn: txnList){ - PostRes postRes = PostRes.toDto(txn, transactionAttachService.getFirstImageName(txn)); + GetPostsRes postRes = GetPostsRes.toDto(txn, transactionAttachService.getFirstImageName(txn)); postResList.add(postRes); } From b76f5d3a89ac3f32862bdab1668131a3ad6f17f3 Mon Sep 17 00:00:00 2001 From: isExample Date: Sat, 23 Sep 2023 18:39:41 +0900 Subject: [PATCH 08/16] =?UTF-8?q?[Feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API(=EC=B6=94?= =?UTF-8?q?=ED=9B=84=20=EB=8D=94=EB=AF=B8=20=EB=B3=80=EA=B2=BD=20=ED=95=84?= =?UTF-8?q?=EC=9A=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TransactionController.java | 8 ++++ .../transaction/dto/GetPostDetailRes.java | 38 +++++++++++++++++++ .../repository/TransactionRepository.java | 1 + .../service/TransactionAttachService.java | 9 +++++ .../service/TransactionService.java | 17 +++++++++ 5 files changed, 73 insertions(+) create mode 100644 src/main/java/HeyPorori/transaction/dto/GetPostDetailRes.java diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index 847548d..1ea72a9 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -4,6 +4,7 @@ import HeyPorori.transaction.config.BaseResponse; import HeyPorori.transaction.config.BaseResponseStatus; import HeyPorori.transaction.dto.CreatePostReq; +import HeyPorori.transaction.dto.GetPostDetailRes; import HeyPorori.transaction.dto.GetPostsRes; import HeyPorori.transaction.dto.PreSignedUrlRes; import HeyPorori.transaction.service.AmazonS3Service; @@ -65,4 +66,11 @@ public BaseResponse getPreSignedUrl(@RequestHeader("Authorizati public BaseResponse> getAllPostByCategory(String category) throws BaseException { return new BaseResponse<>(transactionService.findAllPostByCategory(category)); } + + @Operation(summary = "중고거래 게시글 상세 조회 API", description = "중고거래 서비스의 거래 게시글 상세정보를 조회하기 위한 API입니다.") + @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) + @GetMapping("/post/{transactionId}") + public BaseResponse getPostDetail(@PathVariable Long transactionId) throws BaseException { + return new BaseResponse<>(transactionService.getPostDetail(transactionId)); + } } diff --git a/src/main/java/HeyPorori/transaction/dto/GetPostDetailRes.java b/src/main/java/HeyPorori/transaction/dto/GetPostDetailRes.java new file mode 100644 index 0000000..7ff0256 --- /dev/null +++ b/src/main/java/HeyPorori/transaction/dto/GetPostDetailRes.java @@ -0,0 +1,38 @@ +package HeyPorori.transaction.dto; + +import HeyPorori.transaction.domain.Transaction; +import HeyPorori.transaction.domain.UserInfo; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class GetPostDetailRes { + private Long transactionId; + private String title; + private String content; + private String nickName; + private String address; + private String createdAt; + private int recommend; + private List imageNameList; + + public static GetPostDetailRes toDto(Transaction transaction, String nickName, String createdAt, List imageNameList){ + return GetPostDetailRes.builder() + .transactionId(transaction.getTransactionId()) + .title(transaction.getTitle()) + .content(transaction.getContent()) + .nickName(nickName) + .address(transaction.getAddress()) + .createdAt(createdAt) + .recommend(transaction.getRecommendList().size()) + .imageNameList(imageNameList) + .build(); + } +} diff --git a/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java b/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java index 9d8a56e..2a86423 100644 --- a/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java +++ b/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java @@ -11,5 +11,6 @@ @Repository public interface TransactionRepository extends JpaRepository { List findByStatus(String status); + Transaction findByTransactionIdAndStatus(Long transactionId, String status); List findByCategoryAndStatus(Category category, String status); } diff --git a/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java b/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java index 3e661a6..ec0ad43 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionAttachService.java @@ -32,4 +32,13 @@ public String getFirstImageName(Transaction transaction){ return attachList.get(0).getImageUrl(); } } + + public List getImageNameList(Transaction transaction){ + List attachList = transaction.getAttachList(); + List nameList = new ArrayList<>(); + for(TransactionAttach attach: attachList){ + nameList.add(attach.getImageUrl()); + } + return nameList; + } } diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index 3e393f0..29b5228 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -3,12 +3,15 @@ import HeyPorori.transaction.domain.Category; import HeyPorori.transaction.domain.Transaction; import HeyPorori.transaction.dto.CreatePostReq; +import HeyPorori.transaction.dto.GetPostDetailRes; import HeyPorori.transaction.dto.GetPostsRes; import HeyPorori.transaction.repository.TransactionRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; @@ -43,4 +46,18 @@ public List findAllPostByCategory(String category){ return postResList; } + + public GetPostDetailRes getPostDetail(Long transactionId){ + // 더미 닉네임 - 추후 변경 + String nickName = "dummy_data"; + Transaction txn = transactionRepository.findByTransactionIdAndStatus(transactionId, "ACTIVE"); + List imageNameList = transactionAttachService.getImageNameList(txn); + GetPostDetailRes postDetailRes = GetPostDetailRes.toDto(txn, nickName, toFormattedDate(txn.getCreatedAt()), imageNameList); + return postDetailRes; + } + + public String toFormattedDate(LocalDateTime baseDateTime){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd"); + return baseDateTime.format(formatter); + } } From b95feff9893fd245fd87ac88ee63d612f8a25ec2 Mon Sep 17 00:00:00 2001 From: isExample Date: Sat, 23 Sep 2023 18:42:49 +0900 Subject: [PATCH 09/16] =?UTF-8?q?[Refactor]=20Response=20DTO=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20Get=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TransactionController.java | 8 ++++---- .../{GetPostDetailRes.java => PostDetailRes.java} | 7 +++---- .../dto/{GetPostsRes.java => PostsRes.java} | 6 +++--- .../transaction/service/TransactionService.java | 14 +++++++------- 4 files changed, 17 insertions(+), 18 deletions(-) rename src/main/java/HeyPorori/transaction/dto/{GetPostDetailRes.java => PostDetailRes.java} (79%) rename src/main/java/HeyPorori/transaction/dto/{GetPostsRes.java => PostsRes.java} (80%) diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index 1ea72a9..fb7156a 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -4,8 +4,8 @@ import HeyPorori.transaction.config.BaseResponse; import HeyPorori.transaction.config.BaseResponseStatus; import HeyPorori.transaction.dto.CreatePostReq; -import HeyPorori.transaction.dto.GetPostDetailRes; -import HeyPorori.transaction.dto.GetPostsRes; +import HeyPorori.transaction.dto.PostDetailRes; +import HeyPorori.transaction.dto.PostsRes; import HeyPorori.transaction.dto.PreSignedUrlRes; import HeyPorori.transaction.service.AmazonS3Service; import HeyPorori.transaction.service.TransactionService; @@ -63,14 +63,14 @@ public BaseResponse getPreSignedUrl(@RequestHeader("Authorizati @Operation(summary = "중고거래 게시글 목록 조회 API", description = "중고거래 서비스의 거래 게시글 목록을 조회하기 위한 API입니다.") @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) @GetMapping("/post") - public BaseResponse> getAllPostByCategory(String category) throws BaseException { + public BaseResponse> getAllPostByCategory(String category) throws BaseException { return new BaseResponse<>(transactionService.findAllPostByCategory(category)); } @Operation(summary = "중고거래 게시글 상세 조회 API", description = "중고거래 서비스의 거래 게시글 상세정보를 조회하기 위한 API입니다.") @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) @GetMapping("/post/{transactionId}") - public BaseResponse getPostDetail(@PathVariable Long transactionId) throws BaseException { + public BaseResponse getPostDetail(@PathVariable Long transactionId) throws BaseException { return new BaseResponse<>(transactionService.getPostDetail(transactionId)); } } diff --git a/src/main/java/HeyPorori/transaction/dto/GetPostDetailRes.java b/src/main/java/HeyPorori/transaction/dto/PostDetailRes.java similarity index 79% rename from src/main/java/HeyPorori/transaction/dto/GetPostDetailRes.java rename to src/main/java/HeyPorori/transaction/dto/PostDetailRes.java index 7ff0256..50503c3 100644 --- a/src/main/java/HeyPorori/transaction/dto/GetPostDetailRes.java +++ b/src/main/java/HeyPorori/transaction/dto/PostDetailRes.java @@ -1,7 +1,6 @@ package HeyPorori.transaction.dto; import HeyPorori.transaction.domain.Transaction; -import HeyPorori.transaction.domain.UserInfo; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -13,7 +12,7 @@ @Builder @NoArgsConstructor @AllArgsConstructor -public class GetPostDetailRes { +public class PostDetailRes { private Long transactionId; private String title; private String content; @@ -23,8 +22,8 @@ public class GetPostDetailRes { private int recommend; private List imageNameList; - public static GetPostDetailRes toDto(Transaction transaction, String nickName, String createdAt, List imageNameList){ - return GetPostDetailRes.builder() + public static PostDetailRes toDto(Transaction transaction, String nickName, String createdAt, List imageNameList){ + return PostDetailRes.builder() .transactionId(transaction.getTransactionId()) .title(transaction.getTitle()) .content(transaction.getContent()) diff --git a/src/main/java/HeyPorori/transaction/dto/GetPostsRes.java b/src/main/java/HeyPorori/transaction/dto/PostsRes.java similarity index 80% rename from src/main/java/HeyPorori/transaction/dto/GetPostsRes.java rename to src/main/java/HeyPorori/transaction/dto/PostsRes.java index f6b59a1..54822c7 100644 --- a/src/main/java/HeyPorori/transaction/dto/GetPostsRes.java +++ b/src/main/java/HeyPorori/transaction/dto/PostsRes.java @@ -10,14 +10,14 @@ @Builder @NoArgsConstructor @AllArgsConstructor -public class GetPostsRes { +public class PostsRes { private String title; private String imageName; private String address; private int recommend; - public static GetPostsRes toDto(Transaction transaction, String imageName){ - return GetPostsRes.builder() + public static PostsRes toDto(Transaction transaction, String imageName){ + return PostsRes.builder() .title(transaction.getTitle()) .imageName(imageName) .address(transaction.getAddress()) diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index 29b5228..af66ddd 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -3,8 +3,8 @@ import HeyPorori.transaction.domain.Category; import HeyPorori.transaction.domain.Transaction; import HeyPorori.transaction.dto.CreatePostReq; -import HeyPorori.transaction.dto.GetPostDetailRes; -import HeyPorori.transaction.dto.GetPostsRes; +import HeyPorori.transaction.dto.PostDetailRes; +import HeyPorori.transaction.dto.PostsRes; import HeyPorori.transaction.repository.TransactionRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -30,7 +30,7 @@ public void createPost(String token, CreatePostReq postReq) { transactionRepository.save(txn); } - public List findAllPostByCategory(String category){ + public List findAllPostByCategory(String category){ List txnList = new ArrayList<>(); if(category.equals("NONE")){ txnList = transactionRepository.findByStatus("ACTIVE"); @@ -38,21 +38,21 @@ public List findAllPostByCategory(String category){ txnList = transactionRepository.findByCategoryAndStatus(Category.parsing(category), "ACTIVE"); } - List postResList = new ArrayList<>(); + List postResList = new ArrayList<>(); for(Transaction txn: txnList){ - GetPostsRes postRes = GetPostsRes.toDto(txn, transactionAttachService.getFirstImageName(txn)); + PostsRes postRes = PostsRes.toDto(txn, transactionAttachService.getFirstImageName(txn)); postResList.add(postRes); } return postResList; } - public GetPostDetailRes getPostDetail(Long transactionId){ + public PostDetailRes getPostDetail(Long transactionId){ // 더미 닉네임 - 추후 변경 String nickName = "dummy_data"; Transaction txn = transactionRepository.findByTransactionIdAndStatus(transactionId, "ACTIVE"); List imageNameList = transactionAttachService.getImageNameList(txn); - GetPostDetailRes postDetailRes = GetPostDetailRes.toDto(txn, nickName, toFormattedDate(txn.getCreatedAt()), imageNameList); + PostDetailRes postDetailRes = PostDetailRes.toDto(txn, nickName, toFormattedDate(txn.getCreatedAt()), imageNameList); return postDetailRes; } From 199930fbc91a6b82aaa7ac2037b75d584ca67499 Mon Sep 17 00:00:00 2001 From: isExample Date: Sat, 23 Sep 2023 22:27:05 +0900 Subject: [PATCH 10/16] =?UTF-8?q?[Feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transaction/config/BaseResponseStatus.java | 4 +++- .../controller/TransactionController.java | 8 ++++++++ .../repository/TransactionRepository.java | 2 +- .../transaction/service/TransactionService.java | 14 +++++++++++++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java b/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java index 3a5d38e..0651544 100644 --- a/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java +++ b/src/main/java/HeyPorori/transaction/config/BaseResponseStatus.java @@ -10,7 +10,9 @@ public enum BaseResponseStatus { /* 요청 실패 */ USER_INVALID_RESPONSE(false, 1050, "User 서비스로부터 올바른 응답을 받지 못하였습니다."), INVALID_JWT(false, 1051, "잘못된 JWT 토큰입니다."), - INVALID_CATEGORY(false, 3001, "유효하지 않은 카테고리입니다.") + INVALID_CATEGORY(false, 3001, "유효하지 않은 카테고리입니다."), + POST_NOT_FOUND(false, 3010, "존재하지 않는 게시글입니다."), + INVALID_POST_OWNER(false, 3011, "게시글 작성자가 아닙니다.") ; diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index fb7156a..a291029 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -73,4 +73,12 @@ public BaseResponse> getAllPostByCategory(String category) throws public BaseResponse getPostDetail(@PathVariable Long transactionId) throws BaseException { return new BaseResponse<>(transactionService.getPostDetail(transactionId)); } + + @Operation(summary = "중고거래 게시글 삭제 API", description = "중고거래 서비스의 거래 게시글을 삭제하기 위한 API입니다.") + @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) + @DeleteMapping("/post/{transactionId}") + public BaseResponse deletePost(@RequestHeader("Authorization") String token, @PathVariable Long transactionId) throws BaseException { + transactionService.deletePost(token, transactionId); + return new BaseResponse<>("게시글이 삭제되었습니다."); + } } diff --git a/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java b/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java index 2a86423..c2d4285 100644 --- a/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java +++ b/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java @@ -11,6 +11,6 @@ @Repository public interface TransactionRepository extends JpaRepository { List findByStatus(String status); - Transaction findByTransactionIdAndStatus(Long transactionId, String status); + Optional findByTransactionIdAndStatus(Long transactionId, String status); List findByCategoryAndStatus(Category category, String status); } diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index af66ddd..43a907e 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -1,5 +1,7 @@ package HeyPorori.transaction.service; +import HeyPorori.transaction.config.BaseException; +import HeyPorori.transaction.config.BaseResponseStatus; import HeyPorori.transaction.domain.Category; import HeyPorori.transaction.domain.Transaction; import HeyPorori.transaction.dto.CreatePostReq; @@ -50,12 +52,22 @@ public List findAllPostByCategory(String category){ public PostDetailRes getPostDetail(Long transactionId){ // 더미 닉네임 - 추후 변경 String nickName = "dummy_data"; - Transaction txn = transactionRepository.findByTransactionIdAndStatus(transactionId, "ACTIVE"); + Transaction txn = transactionRepository.findByTransactionIdAndStatus(transactionId, "ACTIVE") + .orElseThrow(() -> new BaseException(BaseResponseStatus.POST_NOT_FOUND)); List imageNameList = transactionAttachService.getImageNameList(txn); PostDetailRes postDetailRes = PostDetailRes.toDto(txn, nickName, toFormattedDate(txn.getCreatedAt()), imageNameList); return postDetailRes; } + public void deletePost(String token, Long transactionId){ + Long userId = userService.getUserId(token); + Transaction txn = transactionRepository.findByTransactionIdAndStatus(transactionId, "ACTIVE") + .orElseThrow(() -> new BaseException(BaseResponseStatus.POST_NOT_FOUND)); + if(userId != txn.getUserId()) throw new BaseException(BaseResponseStatus.INVALID_POST_OWNER); + txn.changeStatus("INACTIVE"); + transactionRepository.save(txn); + } + public String toFormattedDate(LocalDateTime baseDateTime){ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd"); return baseDateTime.format(formatter); From 434a476054381ffea8bfd68e83fee5c51336f8c7 Mon Sep 17 00:00:00 2001 From: isExample Date: Sat, 23 Sep 2023 22:31:05 +0900 Subject: [PATCH 11/16] =?UTF-8?q?[Fix]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20API=20-=20Response=20?= =?UTF-8?q?DTO=EC=97=90=20transactionId=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/HeyPorori/transaction/dto/PostsRes.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/HeyPorori/transaction/dto/PostsRes.java b/src/main/java/HeyPorori/transaction/dto/PostsRes.java index 54822c7..bbc7df9 100644 --- a/src/main/java/HeyPorori/transaction/dto/PostsRes.java +++ b/src/main/java/HeyPorori/transaction/dto/PostsRes.java @@ -11,6 +11,7 @@ @NoArgsConstructor @AllArgsConstructor public class PostsRes { + private Long transactionId; private String title; private String imageName; private String address; @@ -18,6 +19,7 @@ public class PostsRes { public static PostsRes toDto(Transaction transaction, String imageName){ return PostsRes.builder() + .transactionId(transaction.getTransactionId()) .title(transaction.getTitle()) .imageName(imageName) .address(transaction.getAddress()) From 7575f48cfcc9a55ca1cfb2bd5c91b98d733ab3ae Mon Sep 17 00:00:00 2001 From: isExample Date: Sun, 24 Sep 2023 00:09:55 +0900 Subject: [PATCH 12/16] =?UTF-8?q?[Fix]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20-=20=EB=8D=94?= =?UTF-8?q?=EB=AF=B8=20=EC=A0=9C=EA=B1=B0=20&=20Response=20DTO=EC=97=90=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=EC=9E=90=20=EB=B3=B8=EC=9D=B8=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TransactionController.java | 4 ++-- .../transaction/dto/PostDetailRes.java | 4 +++- .../transaction/dto/UserInfoRes.java | 20 +++++++++++++++++++ .../service/TransactionService.java | 10 ++++++---- .../transaction/service/UserService.java | 3 +++ 5 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 src/main/java/HeyPorori/transaction/dto/UserInfoRes.java diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index a291029..e6ff5cc 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -70,8 +70,8 @@ public BaseResponse> getAllPostByCategory(String category) throws @Operation(summary = "중고거래 게시글 상세 조회 API", description = "중고거래 서비스의 거래 게시글 상세정보를 조회하기 위한 API입니다.") @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) @GetMapping("/post/{transactionId}") - public BaseResponse getPostDetail(@PathVariable Long transactionId) throws BaseException { - return new BaseResponse<>(transactionService.getPostDetail(transactionId)); + public BaseResponse getPostDetail(@RequestHeader("Authorization") String token, @PathVariable Long transactionId) throws BaseException { + return new BaseResponse<>(transactionService.getPostDetail(token, transactionId)); } @Operation(summary = "중고거래 게시글 삭제 API", description = "중고거래 서비스의 거래 게시글을 삭제하기 위한 API입니다.") diff --git a/src/main/java/HeyPorori/transaction/dto/PostDetailRes.java b/src/main/java/HeyPorori/transaction/dto/PostDetailRes.java index 50503c3..1fa5223 100644 --- a/src/main/java/HeyPorori/transaction/dto/PostDetailRes.java +++ b/src/main/java/HeyPorori/transaction/dto/PostDetailRes.java @@ -21,8 +21,9 @@ public class PostDetailRes { private String createdAt; private int recommend; private List imageNameList; + private boolean isOwner; - public static PostDetailRes toDto(Transaction transaction, String nickName, String createdAt, List imageNameList){ + public static PostDetailRes toDto(Transaction transaction, String nickName, String createdAt, List imageNameList, boolean isOwner){ return PostDetailRes.builder() .transactionId(transaction.getTransactionId()) .title(transaction.getTitle()) @@ -32,6 +33,7 @@ public static PostDetailRes toDto(Transaction transaction, String nickName, Stri .createdAt(createdAt) .recommend(transaction.getRecommendList().size()) .imageNameList(imageNameList) + .isOwner(isOwner) .build(); } } diff --git a/src/main/java/HeyPorori/transaction/dto/UserInfoRes.java b/src/main/java/HeyPorori/transaction/dto/UserInfoRes.java new file mode 100644 index 0000000..3464e49 --- /dev/null +++ b/src/main/java/HeyPorori/transaction/dto/UserInfoRes.java @@ -0,0 +1,20 @@ +package HeyPorori.transaction.dto; + +import HeyPorori.transaction.domain.Transaction; +import HeyPorori.transaction.domain.UserInfo; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class UserInfoRes { + private long userId; + private String nickName; + + public static UserInfoRes toDto(UserInfo userInfo){ + return UserInfoRes.builder() + .userId(userInfo.getUserId()) + .nickName(userInfo.getNickName()) + .build(); + } +} diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index 43a907e..9d697d3 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -7,6 +7,7 @@ import HeyPorori.transaction.dto.CreatePostReq; import HeyPorori.transaction.dto.PostDetailRes; import HeyPorori.transaction.dto.PostsRes; +import HeyPorori.transaction.dto.UserInfoRes; import HeyPorori.transaction.repository.TransactionRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -49,13 +50,14 @@ public List findAllPostByCategory(String category){ return postResList; } - public PostDetailRes getPostDetail(Long transactionId){ - // 더미 닉네임 - 추후 변경 - String nickName = "dummy_data"; + public PostDetailRes getPostDetail(String token, Long transactionId){ Transaction txn = transactionRepository.findByTransactionIdAndStatus(transactionId, "ACTIVE") .orElseThrow(() -> new BaseException(BaseResponseStatus.POST_NOT_FOUND)); + UserInfoRes userInfoRes = userService.getUserIdAndNickName(token); + boolean isOwner = false; + if(userInfoRes.getUserId() == txn.getUserId()) isOwner = true; List imageNameList = transactionAttachService.getImageNameList(txn); - PostDetailRes postDetailRes = PostDetailRes.toDto(txn, nickName, toFormattedDate(txn.getCreatedAt()), imageNameList); + PostDetailRes postDetailRes = PostDetailRes.toDto(txn, userInfoRes.getNickName(), toFormattedDate(txn.getCreatedAt()), imageNameList, isOwner); return postDetailRes; } diff --git a/src/main/java/HeyPorori/transaction/service/UserService.java b/src/main/java/HeyPorori/transaction/service/UserService.java index 025eaa7..3749c7e 100644 --- a/src/main/java/HeyPorori/transaction/service/UserService.java +++ b/src/main/java/HeyPorori/transaction/service/UserService.java @@ -4,6 +4,7 @@ import HeyPorori.transaction.config.BaseResponse; import HeyPorori.transaction.config.BaseResponseStatus; import HeyPorori.transaction.domain.UserInfo; +import HeyPorori.transaction.dto.UserInfoRes; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.core.ParameterizedTypeReference; @@ -21,6 +22,8 @@ public Long getUserId(String token) { return postTokenRequest(token).getUserId(); } + public UserInfoRes getUserIdAndNickName(String token){ return UserInfoRes.toDto(postTokenRequest(token)); } + private UserInfo postTokenRequest(String token) { return webClient.get() .uri("/token/me") From 4763873576b6887c740d0ce2c987ce8dcdb88326 Mon Sep 17 00:00:00 2001 From: isExample Date: Mon, 25 Sep 2023 23:02:05 +0900 Subject: [PATCH 13/16] =?UTF-8?q?[Fix]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20-=20Response=20?= =?UTF-8?q?DTO=EC=97=90=20=EC=B6=94=EC=B2=9C=20=EC=97=AC=EB=B6=80=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/HeyPorori/transaction/dto/PostDetailRes.java | 4 +++- .../transaction/repository/RecommendRepository.java | 4 ++++ .../HeyPorori/transaction/service/TransactionService.java | 5 ++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/HeyPorori/transaction/dto/PostDetailRes.java b/src/main/java/HeyPorori/transaction/dto/PostDetailRes.java index 1fa5223..1753828 100644 --- a/src/main/java/HeyPorori/transaction/dto/PostDetailRes.java +++ b/src/main/java/HeyPorori/transaction/dto/PostDetailRes.java @@ -22,8 +22,9 @@ public class PostDetailRes { private int recommend; private List imageNameList; private boolean isOwner; + private boolean isRecommended; - public static PostDetailRes toDto(Transaction transaction, String nickName, String createdAt, List imageNameList, boolean isOwner){ + public static PostDetailRes toDto(Transaction transaction, String nickName, String createdAt, List imageNameList, boolean isOwner, boolean isRecommended){ return PostDetailRes.builder() .transactionId(transaction.getTransactionId()) .title(transaction.getTitle()) @@ -34,6 +35,7 @@ public static PostDetailRes toDto(Transaction transaction, String nickName, Stri .recommend(transaction.getRecommendList().size()) .imageNameList(imageNameList) .isOwner(isOwner) + .isRecommended(isRecommended) .build(); } } diff --git a/src/main/java/HeyPorori/transaction/repository/RecommendRepository.java b/src/main/java/HeyPorori/transaction/repository/RecommendRepository.java index c11f5f1..ab8aa20 100644 --- a/src/main/java/HeyPorori/transaction/repository/RecommendRepository.java +++ b/src/main/java/HeyPorori/transaction/repository/RecommendRepository.java @@ -1,9 +1,13 @@ package HeyPorori.transaction.repository; import HeyPorori.transaction.domain.Recommend; +import HeyPorori.transaction.domain.Transaction; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface RecommendRepository extends JpaRepository { + boolean existsByTransactionIdAndUserId(Transaction transaction, Long userId); } diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index 9d697d3..5ac31e9 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -8,6 +8,7 @@ import HeyPorori.transaction.dto.PostDetailRes; import HeyPorori.transaction.dto.PostsRes; import HeyPorori.transaction.dto.UserInfoRes; +import HeyPorori.transaction.repository.RecommendRepository; import HeyPorori.transaction.repository.TransactionRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -25,6 +26,7 @@ public class TransactionService { private final TransactionRepository transactionRepository; private final UserService userService; private final TransactionAttachService transactionAttachService; + private final RecommendRepository recommendRepository; public void createPost(String token, CreatePostReq postReq) { userService.sendTestJwtRequest(token); @@ -57,7 +59,8 @@ public PostDetailRes getPostDetail(String token, Long transactionId){ boolean isOwner = false; if(userInfoRes.getUserId() == txn.getUserId()) isOwner = true; List imageNameList = transactionAttachService.getImageNameList(txn); - PostDetailRes postDetailRes = PostDetailRes.toDto(txn, userInfoRes.getNickName(), toFormattedDate(txn.getCreatedAt()), imageNameList, isOwner); + boolean isRecommends = recommendRepository.existsByTransactionIdAndUserId(txn, userInfoRes.getUserId()); + PostDetailRes postDetailRes = PostDetailRes.toDto(txn, userInfoRes.getNickName(), toFormattedDate(txn.getCreatedAt()), imageNameList, isOwner, isRecommends); return postDetailRes; } From 9c01086db794b8a3ef20c687c170220c82a68704 Mon Sep 17 00:00:00 2001 From: isExample Date: Mon, 25 Sep 2023 23:36:58 +0900 Subject: [PATCH 14/16] =?UTF-8?q?[Fix]=20Recommend=20Entity=EC=97=90=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/HeyPorori/transaction/domain/Recommend.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/HeyPorori/transaction/domain/Recommend.java b/src/main/java/HeyPorori/transaction/domain/Recommend.java index 273ebd1..a46799e 100644 --- a/src/main/java/HeyPorori/transaction/domain/Recommend.java +++ b/src/main/java/HeyPorori/transaction/domain/Recommend.java @@ -2,6 +2,7 @@ import HeyPorori.transaction.config.BaseTimeEntity; import lombok.*; +import org.hibernate.annotations.ColumnDefault; import javax.persistence.*; @@ -23,6 +24,9 @@ public class Recommend extends BaseTimeEntity { @Column(name = "user_id", nullable = false) private Long userId; + @ColumnDefault("'ACTIVE'") + private String status; + @Builder public Recommend(Transaction transactionId, Long userId){ this.transactionId = transactionId; From 650d9ddd1c7228ec71aa605dc29d9b171cc28154 Mon Sep 17 00:00:00 2001 From: isExample Date: Tue, 26 Sep 2023 00:34:27 +0900 Subject: [PATCH 15/16] =?UTF-8?q?[Feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=B6=94=EC=B2=9C=20=EB=B0=8F=20=EC=B6=94=EC=B2=9C=20=EC=B7=A8?= =?UTF-8?q?=EC=86=8C=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TransactionController.java | 13 ++++++---- .../transaction/domain/Recommend.java | 19 ++++++++++++++- .../transaction/dto/RecommendPostReq.java | 19 +++++++++++++++ .../repository/RecommendRepository.java | 2 ++ .../service/TransactionService.java | 24 +++++++++++++++---- 5 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 src/main/java/HeyPorori/transaction/dto/RecommendPostReq.java diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index e6ff5cc..9104dbe 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -3,10 +3,7 @@ import HeyPorori.transaction.config.BaseException; import HeyPorori.transaction.config.BaseResponse; import HeyPorori.transaction.config.BaseResponseStatus; -import HeyPorori.transaction.dto.CreatePostReq; -import HeyPorori.transaction.dto.PostDetailRes; -import HeyPorori.transaction.dto.PostsRes; -import HeyPorori.transaction.dto.PreSignedUrlRes; +import HeyPorori.transaction.dto.*; import HeyPorori.transaction.service.AmazonS3Service; import HeyPorori.transaction.service.TransactionService; import HeyPorori.transaction.service.UserService; @@ -81,4 +78,12 @@ public BaseResponse deletePost(@RequestHeader("Authorization") String to transactionService.deletePost(token, transactionId); return new BaseResponse<>("게시글이 삭제되었습니다."); } + + @Operation(summary = "중고거래 게시글 추천 API", description = "중고거래 서비스의 거래 게시글을 추천하거나 추천 취소하기 위한 API입니다.") + @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) + @PostMapping("/recommend") + public BaseResponse recommendPost(@RequestHeader("Authorization") String token, @RequestBody RecommendPostReq req) throws BaseException { + transactionService.recommendPost(token, req); + return new BaseResponse<>("게시글을 추천했습니다."); + } } diff --git a/src/main/java/HeyPorori/transaction/domain/Recommend.java b/src/main/java/HeyPorori/transaction/domain/Recommend.java index a46799e..eb9f302 100644 --- a/src/main/java/HeyPorori/transaction/domain/Recommend.java +++ b/src/main/java/HeyPorori/transaction/domain/Recommend.java @@ -1,8 +1,11 @@ package HeyPorori.transaction.domain; import HeyPorori.transaction.config.BaseTimeEntity; +import HeyPorori.transaction.dto.CreatePostReq; import lombok.*; import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; import javax.persistence.*; @@ -11,6 +14,8 @@ @Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Table(name = "recommend") +@DynamicInsert +@DynamicUpdate public class Recommend extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -28,8 +33,20 @@ public class Recommend extends BaseTimeEntity { private String status; @Builder - public Recommend(Transaction transactionId, Long userId){ + public Recommend(Transaction transactionId, Long userId, String status){ this.transactionId = transactionId; this.userId = userId; + this.status = status; + } + + public static Recommend toEntity(Transaction transaction, Long userId){ + return Recommend.builder() + .transactionId(transaction) + .userId(userId) + .build(); + } + + public void changeStatus(String status) { + this.status = status; } } \ No newline at end of file diff --git a/src/main/java/HeyPorori/transaction/dto/RecommendPostReq.java b/src/main/java/HeyPorori/transaction/dto/RecommendPostReq.java new file mode 100644 index 0000000..5411dcb --- /dev/null +++ b/src/main/java/HeyPorori/transaction/dto/RecommendPostReq.java @@ -0,0 +1,19 @@ +package HeyPorori.transaction.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import java.util.List; +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class RecommendPostReq { + private Long transactionId; + @Pattern(regexp = "^(INACTIVE|ACTIVE)$", message = "유효하지 않은 상태입니다.") + private String toStatus; + @Pattern(regexp = "^(INACTIVE|ACTIVE)$", message = "유효하지 않은 상태입니다.") + private String fromStatus; +} \ No newline at end of file diff --git a/src/main/java/HeyPorori/transaction/repository/RecommendRepository.java b/src/main/java/HeyPorori/transaction/repository/RecommendRepository.java index ab8aa20..b92c657 100644 --- a/src/main/java/HeyPorori/transaction/repository/RecommendRepository.java +++ b/src/main/java/HeyPorori/transaction/repository/RecommendRepository.java @@ -5,9 +5,11 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import javax.swing.text.html.Option; import java.util.Optional; @Repository public interface RecommendRepository extends JpaRepository { boolean existsByTransactionIdAndUserId(Transaction transaction, Long userId); + Recommend findByTransactionIdAndUserIdAndStatus(Transaction transaction, Long userId, String status); } diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index 5ac31e9..2a3c7b9 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -3,11 +3,9 @@ import HeyPorori.transaction.config.BaseException; import HeyPorori.transaction.config.BaseResponseStatus; import HeyPorori.transaction.domain.Category; +import HeyPorori.transaction.domain.Recommend; import HeyPorori.transaction.domain.Transaction; -import HeyPorori.transaction.dto.CreatePostReq; -import HeyPorori.transaction.dto.PostDetailRes; -import HeyPorori.transaction.dto.PostsRes; -import HeyPorori.transaction.dto.UserInfoRes; +import HeyPorori.transaction.dto.*; import HeyPorori.transaction.repository.RecommendRepository; import HeyPorori.transaction.repository.TransactionRepository; import lombok.RequiredArgsConstructor; @@ -18,6 +16,7 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; +import java.util.Optional; @Service @Transactional @@ -73,6 +72,23 @@ public void deletePost(String token, Long transactionId){ transactionRepository.save(txn); } + public void recommendPost(String token, RecommendPostReq req){ + Long userId = userService.getUserId(token); + Transaction txn = transactionRepository.findByTransactionIdAndStatus(req.getTransactionId(), "ACTIVE") + .orElseThrow(() -> new BaseException(BaseResponseStatus.POST_NOT_FOUND)); + Recommend recommend = recommendRepository.findByTransactionIdAndUserIdAndStatus(txn, userId, req.getFromStatus()); + if(recommend == null && req.getToStatus().equals("ACTIVE")){ + Recommend newRecommend = Recommend.toEntity(txn, userId); + recommendRepository.save(newRecommend); + } else{ + if(recommend != null && recommend.getStatus().equals(req.getFromStatus())){ + recommend.changeStatus(req.getToStatus()); + } else{ + new IllegalArgumentException("추천 상태가 예상된 상태와 같지 않습니다."); + } + } + } + public String toFormattedDate(LocalDateTime baseDateTime){ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd"); return baseDateTime.format(formatter); From f19943d3e3975ad312c13b038f77fb02cec4e9e6 Mon Sep 17 00:00:00 2001 From: isExample Date: Tue, 26 Sep 2023 01:25:23 +0900 Subject: [PATCH 16/16] =?UTF-8?q?[Feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EA=B2=80=EC=83=89=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TransactionController.java | 9 ++++++++- .../repository/TransactionRepository.java | 1 + .../transaction/service/TransactionService.java | 13 +++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/HeyPorori/transaction/controller/TransactionController.java b/src/main/java/HeyPorori/transaction/controller/TransactionController.java index 9104dbe..1c74ee5 100644 --- a/src/main/java/HeyPorori/transaction/controller/TransactionController.java +++ b/src/main/java/HeyPorori/transaction/controller/TransactionController.java @@ -86,4 +86,11 @@ public BaseResponse recommendPost(@RequestHeader("Authorization") String transactionService.recommendPost(token, req); return new BaseResponse<>("게시글을 추천했습니다."); } -} + + @Operation(summary = "중고거래 게시글 검색 API", description = "중고거래 서비스의 거래 게시글을 검색하기 위한 API입니다.") + @ApiResponse(responseCode = "200", description = "요청 성공", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BaseResponse.class))) + @GetMapping("/search/{keyword}") + public BaseResponse> recommendPost(@PathVariable String keyword) throws BaseException { + return new BaseResponse<>(transactionService.findAllPostByKeyword(keyword)); + } +} \ No newline at end of file diff --git a/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java b/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java index c2d4285..33a2a68 100644 --- a/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java +++ b/src/main/java/HeyPorori/transaction/repository/TransactionRepository.java @@ -13,4 +13,5 @@ public interface TransactionRepository extends JpaRepository List findByStatus(String status); Optional findByTransactionIdAndStatus(Long transactionId, String status); List findByCategoryAndStatus(Category category, String status); + List findByContentContainingAndStatus(String content, String status); } diff --git a/src/main/java/HeyPorori/transaction/service/TransactionService.java b/src/main/java/HeyPorori/transaction/service/TransactionService.java index 2a3c7b9..238d741 100644 --- a/src/main/java/HeyPorori/transaction/service/TransactionService.java +++ b/src/main/java/HeyPorori/transaction/service/TransactionService.java @@ -89,6 +89,19 @@ public void recommendPost(String token, RecommendPostReq req){ } } + public List findAllPostByKeyword(String keyword){ + List txnList = new ArrayList<>(); + txnList = transactionRepository.findByContentContainingAndStatus(keyword, "ACTIVE"); + + List postResList = new ArrayList<>(); + for(Transaction txn: txnList){ + PostsRes postRes = PostsRes.toDto(txn, transactionAttachService.getFirstImageName(txn)); + postResList.add(postRes); + } + + return postResList; + } + public String toFormattedDate(LocalDateTime baseDateTime){ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd"); return baseDateTime.format(formatter);