-
Notifications
You must be signed in to change notification settings - Fork 1
✨Feat: 교환 관련 API 기능 개발 #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
5d23c19
:recycle:Refactor: 게시글 등록 시 카테고리 단일로 수정
uni-j-uni 329e2c4
:recycle:Refactor: 게시글 조회 작성자 확인 수정
uni-j-uni 5d71994
:sparkles:Feat: 의류 교환 API 생성
uni-j-uni 9f6108c
:recycle:Refactor: 코드 포맷 적용
uni-j-uni a808430
:recycle:Refactor: 코드 리뷰 기반 수정사항 반영
uni-j-uni File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
src/main/java/com/sku/refit/domain/exchange/controller/ExchangeController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| /* | ||
| * Copyright (c) SKU 다시입을Lab | ||
| */ | ||
| package com.sku.refit.domain.exchange.controller; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import jakarta.validation.Valid; | ||
|
|
||
| import org.springframework.http.MediaType; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.DeleteMapping; | ||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.PathVariable; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
| import org.springframework.web.bind.annotation.PutMapping; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RequestParam; | ||
| import org.springframework.web.bind.annotation.RequestPart; | ||
| import org.springframework.web.multipart.MultipartFile; | ||
|
|
||
| import com.sku.refit.domain.exchange.dto.request.ExchangePostRequest; | ||
| import com.sku.refit.domain.exchange.dto.response.ExchangePostCardResponse; | ||
| import com.sku.refit.domain.exchange.dto.response.ExchangePostDetailResponse; | ||
| import com.sku.refit.global.page.response.PageResponse; | ||
| import com.sku.refit.global.response.BaseResponse; | ||
|
|
||
| import io.swagger.v3.oas.annotations.Operation; | ||
| import io.swagger.v3.oas.annotations.Parameter; | ||
| import io.swagger.v3.oas.annotations.media.Content; | ||
| import io.swagger.v3.oas.annotations.tags.Tag; | ||
|
|
||
| @Tag(name = "교환 게시글", description = "교환 게시글 관련 API") | ||
| @RequestMapping("/api/exchanges") | ||
| public interface ExchangeController { | ||
|
|
||
| @PostMapping(value = "/new", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | ||
| @Operation(summary = "새 게시글 작성", description = "새 게시글을 작성합니다.") | ||
| ResponseEntity<BaseResponse<ExchangePostDetailResponse>> createExchangePost( | ||
| @Parameter( | ||
| description = "게시글 이미지 리스트", | ||
| content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE)) | ||
| @RequestPart(value = "imageList") | ||
| List<MultipartFile> imageList, | ||
| @Parameter( | ||
| description = "게시글 내용", | ||
| content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)) | ||
| @RequestPart(value = "request") | ||
| @Valid | ||
| ExchangePostRequest request); | ||
|
|
||
| @GetMapping | ||
| @Operation(summary = "교환 게시글 목록(페이지) 조회 (위치 기반)") | ||
| ResponseEntity<BaseResponse<PageResponse<ExchangePostCardResponse>>> getExchangePostsByLocation( | ||
| @Parameter(description = "페이지 번호", example = "1") @RequestParam Integer pageNum, | ||
| @Parameter(description = "페이지 크기", example = "4") @RequestParam Integer pageSize, | ||
| @Parameter(description = "위도", example = "37.544018") | ||
| @RequestParam(defaultValue = "37.544018") | ||
| Double latitude, | ||
| @Parameter(description = "경도", example = "126.951592") | ||
| @RequestParam(defaultValue = "126.951592") | ||
| Double longitude); | ||
|
|
||
| @GetMapping("/{exchangePostId}") | ||
| @Operation(summary = "교환 게시글 단일 조회", description = "교환 게시글 ID로 단일 게시글을 조회합니다.") | ||
| ResponseEntity<BaseResponse<ExchangePostDetailResponse>> getExchangePost( | ||
| @Parameter(description = "교환 게시글 ID", example = "1") @PathVariable Long exchangePostId); | ||
|
|
||
| @PutMapping(value = "/{exchangePostId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | ||
| @Operation(summary = "교환 게시글 수정", description = "특정 교환 게시글을 수정합니다.") | ||
| ResponseEntity<BaseResponse<ExchangePostDetailResponse>> updateExchangePost( | ||
| @Parameter(description = "교환 게시글 ID", example = "1") @PathVariable Long exchangePostId, | ||
| @Parameter( | ||
| description = "수정할 게시글 이미지 리스트", | ||
| content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE)) | ||
| @RequestPart(value = "imageList", required = false) | ||
| List<MultipartFile> imageList, | ||
| @Parameter( | ||
| description = "수정할 게시글 내용", | ||
| content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)) | ||
| @RequestPart(value = "request") | ||
| @Valid | ||
| ExchangePostRequest request); | ||
|
|
||
| @DeleteMapping("/{exchangePostId}") | ||
| @Operation(summary = "교환 게시글 삭제", description = "특정 교환 게시글을 삭제합니다.") | ||
| ResponseEntity<BaseResponse<Void>> deleteExchangePost( | ||
| @Parameter(description = "교환 게시글 ID", example = "1") @PathVariable Long exchangePostId); | ||
| } | ||
89 changes: 89 additions & 0 deletions
89
src/main/java/com/sku/refit/domain/exchange/controller/ExchangeControllerImpl.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| /* | ||
| * Copyright (c) SKU 다시입을Lab | ||
| */ | ||
| package com.sku.refit.domain.exchange.controller; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import jakarta.validation.Valid; | ||
|
|
||
| import org.springframework.data.domain.PageRequest; | ||
| import org.springframework.data.domain.Pageable; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
| import org.springframework.web.multipart.MultipartFile; | ||
|
|
||
| import com.sku.refit.domain.exchange.dto.request.ExchangePostRequest; | ||
| import com.sku.refit.domain.exchange.dto.response.ExchangePostCardResponse; | ||
| import com.sku.refit.domain.exchange.dto.response.ExchangePostDetailResponse; | ||
| import com.sku.refit.domain.exchange.service.ExchangeService; | ||
| import com.sku.refit.global.exception.CustomException; | ||
| import com.sku.refit.global.page.exception.PageErrorStatus; | ||
| import com.sku.refit.global.page.response.PageResponse; | ||
| import com.sku.refit.global.response.BaseResponse; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
|
|
||
| @RestController | ||
| @RequiredArgsConstructor | ||
| public class ExchangeControllerImpl implements ExchangeController { | ||
|
|
||
| private final ExchangeService exchangeService; | ||
|
|
||
| @Override | ||
| public ResponseEntity<BaseResponse<ExchangePostDetailResponse>> createExchangePost( | ||
| List<MultipartFile> imageList, @Valid ExchangePostRequest request) { | ||
|
|
||
| ExchangePostDetailResponse response = exchangeService.createExchangePost(imageList, request); | ||
|
|
||
| return ResponseEntity.ok(BaseResponse.success(response)); | ||
| } | ||
|
|
||
| @Override | ||
| public ResponseEntity<BaseResponse<PageResponse<ExchangePostCardResponse>>> | ||
| getExchangePostsByLocation( | ||
| Integer pageNum, Integer pageSize, Double latitude, Double longitude) { | ||
|
|
||
| if (pageNum < 1) { | ||
| throw new CustomException(PageErrorStatus.PAGE_NOT_FOUND); | ||
| } | ||
| if (pageSize < 1) { | ||
| throw new CustomException(PageErrorStatus.PAGE_SIZE_ERROR); | ||
| } | ||
|
|
||
| Pageable pageable = PageRequest.of(pageNum - 1, pageSize); | ||
| PageResponse<ExchangePostCardResponse> exchangePostCardResponsePageResponse; | ||
|
|
||
| exchangePostCardResponsePageResponse = | ||
| exchangeService.getExchangePostsByLocation(pageable, latitude, longitude); | ||
|
|
||
| return ResponseEntity.ok(BaseResponse.success(exchangePostCardResponsePageResponse)); | ||
| } | ||
|
|
||
| @Override | ||
| public ResponseEntity<BaseResponse<ExchangePostDetailResponse>> getExchangePost( | ||
| Long exchangePostId) { | ||
|
|
||
| ExchangePostDetailResponse response = exchangeService.getExchangePost(exchangePostId); | ||
|
|
||
| return ResponseEntity.ok(BaseResponse.success(response)); | ||
| } | ||
|
|
||
| @Override | ||
| public ResponseEntity<BaseResponse<ExchangePostDetailResponse>> updateExchangePost( | ||
| Long exchangePostId, List<MultipartFile> imageList, @Valid ExchangePostRequest request) { | ||
|
|
||
| ExchangePostDetailResponse response = | ||
| exchangeService.updateExchangePost(exchangePostId, imageList, request); | ||
|
|
||
| return ResponseEntity.ok(BaseResponse.success(response)); | ||
| } | ||
|
|
||
| @Override | ||
| public ResponseEntity<BaseResponse<Void>> deleteExchangePost(Long exchangePostId) { | ||
|
|
||
| exchangeService.deleteExchangePost(exchangePostId); | ||
|
|
||
| return ResponseEntity.ok(BaseResponse.success(null)); | ||
| } | ||
| } |
63 changes: 63 additions & 0 deletions
63
src/main/java/com/sku/refit/domain/exchange/dto/request/ExchangePostRequest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| /* | ||
| * Copyright (c) SKU 다시입을Lab | ||
| */ | ||
| package com.sku.refit.domain.exchange.dto.request; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.NotEmpty; | ||
| import jakarta.validation.constraints.NotNull; | ||
|
|
||
| import com.sku.refit.domain.exchange.entity.ClothSize; | ||
| import com.sku.refit.domain.exchange.entity.ClothStatus; | ||
| import com.sku.refit.domain.exchange.entity.ExchangeCategory; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| @Getter | ||
| @Builder | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Schema(title = "ExchangePostRequest DTO", description = "새 교환 게시물 등록을 위한 데이터 전송") | ||
| public class ExchangePostRequest { | ||
|
|
||
| @NotBlank(message = "교환 게시글 제목은 필수입니다.") | ||
| @Schema(description = "교환 게시글 제목", example = "오버핏 흰색 셔츠") | ||
| private String title; | ||
|
|
||
| @NotNull(message = "교환 카테고리는 필수입니다.") @Schema(description = "교환 카테고리", example = "OUTER") | ||
| private ExchangeCategory exchangeCategory; | ||
|
|
||
| @NotNull(message = "옷 상태는 필수입니다.") @Schema(description = "옷 상태", example = "GOOD") | ||
| private ClothStatus clothStatus; | ||
|
|
||
| @NotNull(message = "옷 사이즈는 필수입니다.") @Schema(description = "옷 사이즈", example = "M") | ||
| private ClothSize clothSize; | ||
|
|
||
| @NotBlank(message = "교환 게시글 설명은 필수입니다.") | ||
| @Schema(description = "교환게시글 설명", example = "아이템에 대한 상세 설명을 작성해주세요.") | ||
| private String description; | ||
|
|
||
| @NotEmpty(message = "교환 선호 카테고리는 필수입니다.") | ||
| @Schema(description = "선호 카테고리") | ||
| private List<ExchangeCategory> preferCategoryList; | ||
|
|
||
| @NotBlank(message = "교환 희망 스팟은 필수입니다.") | ||
| @Schema(description = "교환 희망 스팟", example = "서울역") | ||
| private String exchangeSpot; | ||
|
|
||
| @NotNull(message = "교환 희망 스팟 위도는 필수입니다.") @Schema(description = "교환 희망 스팟 위도", example = "37.544018") | ||
| private Double spotLatitude; | ||
|
|
||
| @NotNull(message = "교환 희망 스팟 경도는 필수입니다.") @Schema(description = "교환 희망 스팟 경도", example = "126.951592") | ||
| private Double spotLongitude; | ||
|
|
||
| @NotBlank(message = "교환 편지는 필수입니다.") | ||
| @Schema(description = "교환 편지", example = "이젠 안녕! 청바지야.") | ||
| private String letter; | ||
| } |
28 changes: 28 additions & 0 deletions
28
src/main/java/com/sku/refit/domain/exchange/dto/response/ExchangePostCardResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| /* | ||
| * Copyright (c) SKU 다시입을Lab | ||
| */ | ||
| package com.sku.refit.domain.exchange.dto.response; | ||
|
|
||
| import com.sku.refit.domain.exchange.entity.ExchangeCategory; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| @Builder | ||
| @Schema(title = "ExchangePostCardResponse DTO", description = "교환글 카드 형식 응답 반환") | ||
| public class ExchangePostCardResponse { | ||
|
|
||
| @Schema(description = "썸네일 이미지 URL") | ||
| private String thumbnailImageUrl; | ||
|
|
||
| @Schema(description = "교환 카테고리", example = "PANTS") | ||
| private ExchangeCategory category; | ||
|
|
||
| @Schema(description = "교환 제목", example = "스판 여성용 빈티지 청바지") | ||
| private String title; | ||
|
|
||
| @Schema(description = "교환 희망 스팟", example = "서울역") | ||
| private String exchangeSpot; | ||
| } |
60 changes: 60 additions & 0 deletions
60
src/main/java/com/sku/refit/domain/exchange/dto/response/ExchangePostDetailResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| /* | ||
| * Copyright (c) SKU 다시입을Lab | ||
| */ | ||
| package com.sku.refit.domain.exchange.dto.response; | ||
|
|
||
| import java.time.LocalDateTime; | ||
| import java.util.List; | ||
|
|
||
| import com.sku.refit.domain.exchange.entity.ClothSize; | ||
| import com.sku.refit.domain.exchange.entity.ClothStatus; | ||
| import com.sku.refit.domain.exchange.entity.ExchangeCategory; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.Builder; | ||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| @Builder | ||
| @Schema(title = "ExchangePostDetailResponse DTO", description = "교환글 상세 정보 응답 반환") | ||
| public class ExchangePostDetailResponse { | ||
|
|
||
| @Schema(description = "교환 게시글 식별자", example = "1") | ||
| private Long exchangePostId; | ||
|
|
||
| @Schema(description = "게시글 작성자", example = "김다입") | ||
| private String nickname; | ||
|
|
||
| @Schema(description = "이미지 URL 리스트") | ||
| private List<String> imageUrlList; | ||
|
|
||
| @Schema(description = "교환 카테고리", example = "PANTS") | ||
| private ExchangeCategory category; | ||
|
|
||
| @Schema(description = "교환 제목", example = "스판 여성용 빈티지 청바지") | ||
| private String title; | ||
|
|
||
| @Schema(description = "옷 사이즈", example = "M") | ||
| private ClothSize size; | ||
|
|
||
| @Schema(description = "옷 상태", example = "GOOD") | ||
| private ClothStatus status; | ||
|
|
||
| @Schema(description = "선호 카테고리") | ||
| private List<ExchangeCategory> preferCategoryList; | ||
|
|
||
| @Schema(description = "교환 희망 스팟", example = "서울역") | ||
| private String exchangeSpot; | ||
|
|
||
| @Schema(description = "교환 희망 스팟 위도", example = "37.544018") | ||
| private Double spotLatitude; | ||
|
|
||
| @Schema(description = "교환 희망 스팟 경도", example = "126.951592") | ||
| private Double spotLongitude; | ||
|
|
||
| @Schema(description = "작성자 본인 여부", example = "true") | ||
| private Boolean isAuthor; | ||
|
|
||
| @Schema(description = "게시글 작성 시간", example = "2025-12-03T14:37:17") | ||
| private LocalDateTime createdAt; | ||
| } |
32 changes: 32 additions & 0 deletions
32
src/main/java/com/sku/refit/domain/exchange/entity/ClothSize.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /* | ||
| * Copyright (c) SKU 다시입을Lab | ||
| */ | ||
| package com.sku.refit.domain.exchange.entity; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.Getter; | ||
| import lombok.RequiredArgsConstructor; | ||
|
|
||
| @Getter | ||
| @RequiredArgsConstructor | ||
| @Schema(description = "옷 사이즈 Enum") | ||
| public enum ClothSize { | ||
| @Schema(description = "FREE") | ||
| FREE, | ||
| @Schema(description = "2XS") | ||
| XS2, | ||
| @Schema(description = "XS") | ||
| XS, | ||
| @Schema(description = "S") | ||
| S, | ||
| @Schema(description = "M") | ||
| M, | ||
| @Schema(description = "L") | ||
| L, | ||
| @Schema(description = "XL") | ||
| XL, | ||
| @Schema(description = "XL2") | ||
| XL2, | ||
| @Schema(description = "XL3") | ||
| XL3; | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.