Skip to content

Commit f747904

Browse files
authored
Merge pull request #12 from NET-ZERO-FitFit/develop
[REFACTOR] 판매 옷 등록 API dto 필수값 수정
2 parents ae51e37 + c681277 commit f747904

8 files changed

Lines changed: 84 additions & 4 deletions

File tree

src/main/java/fitfit/domain/chat/dto/ChatResponseDTO.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fitfit.domain.chat.dto;
22

3+
import io.swagger.v3.oas.annotations.media.Schema;
34
import lombok.Builder;
45
import lombok.Getter;
56

@@ -11,14 +12,18 @@ public class ChatResponseDTO {
1112
@Getter
1213
@Builder
1314
public static class ChatHistoryDTO {
15+
@Schema(description = "채팅 메시지 목록")
1416
private List<ChatMessageDTO> messages;
1517
}
1618

1719
@Getter
1820
@Builder
1921
public static class ChatMessageDTO {
22+
@Schema(example = "user", description = "메시지 발신자 (user 또는 bot)")
2023
private String sender; // "user" or "bot"
24+
@Schema(example = "안녕하세요")
2125
private String content;
26+
@Schema(example = "2025-11-28T12:00:00")
2227
private LocalDateTime createdAt;
2328
}
2429
}

src/main/java/fitfit/domain/clothes/controller/ClothesRestController.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ public class ClothesRestController {
2828
@Operation(summary = "판매 옷 등록 API", description = "자신이 판매할 옷의 정보를 등록하는 API입니다. 이미지는 Base64 인코딩된 문자열로 보내주세요.")
2929
@ApiResponses({
3030
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "OK, 성공"),
31-
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "Bad Request, 잘못된 요청 형식", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
32-
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "존재하지 않는 회원 또는 카테고리", content = @Content(schema = @Schema(implementation = ApiResponse.class)))
31+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "MEMBER4001", description = "존재하지 않는 회원입니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
32+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "CATEGORY4001", description = "존재하지 않는 카테고리입니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
33+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "CLOTHES4001", description = "사이즈 정보가 하나 이상 존재해야 합니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
34+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "CLOTHES4002", description = "직거래 시 주소 정보는 필수입니다.", content = @Content(schema = @Schema(implementation = ApiResponse.class)))
3335
})
3436
public ApiResponse<ClothesResponseDTO.CreateClothesResponse> registerClothes(
3537
@RequestHeader(value = "Authorization") String authorization,

src/main/java/fitfit/domain/clothes/dto/ClothesRequestDTO.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fitfit.domain.clothes.dto;
22

3+
import io.swagger.v3.oas.annotations.media.Schema;
34
import jakarta.validation.constraints.NotBlank;
45
import jakarta.validation.constraints.NotNull;
56
import lombok.Getter;
@@ -15,44 +16,64 @@ public class ClothesRequestDTO {
1516
public static class CreateClothesRequest {
1617

1718
@NotBlank(message = "제목은 필수입니다.")
19+
@Schema(example = "판매글 제목")
1820
private String title;
1921

2022
@NotNull(message = "가격은 필수입니다.")
23+
@Schema(example = "10000")
2124
private Long price;
2225

2326
@NotNull(message = "카테고리 ID는 필수입니다.")
27+
@Schema(example = "1")
2428
private Long categoryId;
2529

2630
@NotBlank(message = "스타일은 필수입니다.")
31+
@Schema(example = "VINTAGE")
2732
private String style;
2833

34+
@Schema(example = "판매글 내용")
2935
private String comment;
3036

31-
@NotBlank(message = "주소는 필수입니다.")
37+
@Schema(example = "서울시 강남구")
3238
private String address;
3339

40+
@Schema(example = "37.4979")
3441
private Double lat;
42+
@Schema(example = "127.0276")
3543
private Double lng;
44+
@Schema(example = "true")
3645
private Boolean saleAgreed;
46+
@Schema(example = "true")
3747
private Boolean meetupAgreed;
48+
@Schema(example = "false")
3849
private Boolean offerAgreed;
3950

4051
// 사이즈 정보
52+
@Schema(example = "100")
4153
private String totalLength;
54+
@Schema(example = "50")
4255
private String chestWidth;
56+
@Schema(example = "45")
4357
private String shoulderWidth;
58+
@Schema(example = "270")
4459
private String footSize;
60+
@Schema(example = "40")
4561
private String waistMeasurement;
62+
@Schema(example = "30")
4663
private String thighMeasurement;
4764

4865
// 판매 정보
66+
@Schema(example = "2025-12-31")
4967
private LocalDate salesPeriod;
68+
@Schema(example = "10")
5069
private Long discountRate;
5170

5271
// Base64 인코딩된 이미지 문자열을 받습니다.
5372
@NotBlank(message = "피팅 이미지는 필수입니다.")
73+
@Schema(example = "data:image/jpeg;base64,...")
5474
private String fittingImage; // "data:image/jpeg;base64,..."
55-
75+
76+
@Schema(example = "[\"data:image/jpeg;base64,...\"]")
5677
private List<String> displayImages;
5778
}
5879
}

src/main/java/fitfit/domain/clothes/dto/ClothesResponseDTO.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fitfit.domain.clothes.dto;
22

3+
import io.swagger.v3.oas.annotations.media.Schema;
34
import lombok.AllArgsConstructor;
45
import lombok.Builder;
56
import lombok.Getter;
@@ -14,7 +15,9 @@ public class ClothesResponseDTO {
1415
@NoArgsConstructor
1516
@AllArgsConstructor
1617
public static class CreateClothesResponse {
18+
@Schema(example = "1")
1719
private Long clothesId;
20+
@Schema(example = "2025-11-28T12:00:00")
1821
private LocalDateTime createdAt;
1922
}
2023
}

src/main/java/fitfit/domain/clothes/service/ClothesCommandServiceImpl.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import lombok.RequiredArgsConstructor;
1919
import org.springframework.stereotype.Service;
2020
import org.springframework.transaction.annotation.Transactional;
21+
import org.springframework.util.StringUtils;
2122

2223
import java.io.IOException;
2324

@@ -45,6 +46,8 @@ public ClothesResponseDTO.CreateClothesResponse createClothes(String authorizati
4546
Category category = categoryRepository.findById(requestDto.getCategoryId())
4647
.orElseThrow(() -> new ClothesHandler(ErrorStatus.CATEGORY_NOT_FOUND));
4748

49+
validateCreateClothesRequest(requestDto);
50+
4851
// 가상 피팅 이미지 업로드 -> 'fitting' 폴더
4952
String fittingImageUrl = s3Service.upload(requestDto.getFittingImage(), "fitting");
5053

@@ -68,4 +71,21 @@ public ClothesResponseDTO.CreateClothesResponse createClothes(String authorizati
6871

6972
return ClothesConverter.toCreateClothesResponse(clothes);
7073
}
74+
75+
private void validateCreateClothesRequest(ClothesRequestDTO.CreateClothesRequest requestDto) {
76+
if (requestDto.getMeetupAgreed() != null && requestDto.getMeetupAgreed()) {
77+
if (!StringUtils.hasText(requestDto.getAddress()) || requestDto.getLat() == null || requestDto.getLng() == null) {
78+
throw new ClothesHandler(ErrorStatus.ADDRESS_NOT_FOUND_FOR_MEETUP);
79+
}
80+
}
81+
82+
if (!StringUtils.hasText(requestDto.getTotalLength()) &&
83+
!StringUtils.hasText(requestDto.getChestWidth()) &&
84+
!StringUtils.hasText(requestDto.getShoulderWidth()) &&
85+
!StringUtils.hasText(requestDto.getFootSize()) &&
86+
!StringUtils.hasText(requestDto.getWaistMeasurement()) &&
87+
!StringUtils.hasText(requestDto.getThighMeasurement())) {
88+
throw new ClothesHandler(ErrorStatus.CLOTHES_SIZE_NOT_FOUND);
89+
}
90+
}
7191
}

src/main/java/fitfit/domain/member/dto/MemberRequestDTO.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public class MemberRequestDTO {
2222
@NoArgsConstructor
2323
public static class KkoOAuth2LoginRequest {
2424
@NotNull(message = "idToken 은 필수입니다.")
25+
@Schema(example = "eyJhbGciOiJSUzI1NiIsImtpZCI6Im...")
2526
private String idToken;
2627
}
2728

@@ -31,6 +32,7 @@ public static class KkoOAuth2LoginRequest {
3132
@AllArgsConstructor
3233
public static class RefreshAccessTokenRequest {
3334
@NotNull(message = "refreshToken 은 필수입니다.")
35+
@Schema(example = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIi...")
3436
private String refreshToken;
3537
}
3638

@@ -40,8 +42,10 @@ public static class RefreshAccessTokenRequest {
4042
@NoArgsConstructor
4143
public static class TermAgreementRequest {
4244
@NotNull(message = "동의 약관 목록은 null일 수 없습니다.")
45+
@Schema(example = "[1, 2]")
4346
private List<Long> agreeTermIdList;
4447
@NotNull(message = "비동의 약관 목록은 null일 수 없습니다. 빈 배열로 넘겨주세요.")
48+
@Schema(example = "[3]")
4549
private List<Long> disagreeTermIdList;
4650
}
4751

@@ -52,6 +56,7 @@ public static class TermAgreementRequest {
5256
public static class NicknameCheckRequest {
5357
@NotNull(message = "닉네임은 필수입니다.")
5458
@Size(max = 25, message = "닉네임은 최대 25자입니다.")
59+
@Schema(example = "fitfit-nickname")
5560
private String nickname;
5661
}
5762

@@ -62,22 +67,31 @@ public static class NicknameCheckRequest {
6267
public static class MemberSignupRequest {
6368
@NotNull(message = "닉네임은 필수입니다.")
6469
@Size(max = 25, message = "닉네임은 최대 25자입니다.")
70+
@Schema(example = "fitfit-nickname")
6571
private String nickname;
6672
@NotNull(message = "이름은 필수입니다.")
6773
@Size(max = 25, message = "이름은 최대 25자입니다.")
74+
@Schema(example = "김핏핏")
6875
private String name; // 실제 이름
6976
@NotNull(message = "키는 필수입니다.")
77+
@Schema(example = "175")
7078
private String height;
7179
@NotNull(message = "몸무게는 필수입니다.")
80+
@Schema(example = "65")
7281
private String weight;
7382
@NotNull(message = "휴대폰 번호는 필수입니다.")
83+
@Schema(example = "010-1234-5678")
7484
private String phoneNumber;
7585
@NotNull(message = "성별은 필수입니다.")
86+
@Schema(example = "MALE")
7687
private Gender gender;
7788
@NotNull(message = "생년월일은 필수입니다.")
89+
@Schema(example = "2000-01-01")
7890
private LocalDate birth;
7991
// null 가능
92+
@Schema(example = "[\"CASUAL\", \"STREET\"]")
8093
private List<Style> styleList;
94+
@Schema(example = "https://fitfit-profile-img.s3.ap-northeast-2.amazonaws.com/full_body.jpg")
8195
private String fullBodyImgUrl;
8296
}
8397

src/main/java/fitfit/domain/member/dto/MemberResponseDTO.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ public class MemberResponseDTO {
1818
@AllArgsConstructor
1919
@NoArgsConstructor
2020
public static class TermAgreementResponse {
21+
@Schema(example = "약관 동의 완료")
2122
private String message;
23+
@Schema(example = "AGREE")
2224
private MemberStatus status;
2325
}
2426

@@ -27,9 +29,13 @@ public static class TermAgreementResponse {
2729
@AllArgsConstructor
2830
@NoArgsConstructor
2931
public static class KkoOAuth2LoginResponse {
32+
@Schema(example = "eyJhbGciOiJIUzI1NiJ9...")
3033
private String accessToken;
34+
@Schema(example = "eyJhbGciOiJIUzI1NiJ9...")
3135
private String refreshToken;
36+
@Schema(example = "2025-11-28T13:00:00")
3237
private LocalDateTime accessTokenExpireAt;
38+
@Schema(example = "AGREE")
3339
private MemberStatus memberStatus;
3440
}
3541

@@ -38,7 +44,9 @@ public static class KkoOAuth2LoginResponse {
3844
@NoArgsConstructor
3945
@AllArgsConstructor
4046
public static class RefreshAccessTokenResponse {
47+
@Schema(example = "eyJhbGciOiJIUzI1NiJ9...")
4148
private String accessToken;
49+
@Schema(example = "2025-11-28T14:00:00")
4250
private LocalDateTime accessTokenExpireAt;
4351
}
4452

@@ -47,8 +55,11 @@ public static class RefreshAccessTokenResponse {
4755
@AllArgsConstructor
4856
@NoArgsConstructor
4957
public static class MemberSignupResponse {
58+
@Schema(example = "fitfit-nickname")
5059
private String nickname;
60+
@Schema(example = "김핏핏")
5161
private String name;
62+
@Schema(example = "ACTIVE")
5263
private MemberStatus status;
5364
}
5465

src/main/java/fitfit/global/apiPayload/code/status/ErrorStatus.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ public enum ErrorStatus implements BaseErrorCode {
4646
// 카테고리 관련
4747
CATEGORY_NOT_FOUND(HttpStatus.NOT_FOUND, "CATEGORY4001", "존재하지 않는 카테고리입니다."),
4848

49+
// 옷 관련
50+
CLOTHES_SIZE_NOT_FOUND(HttpStatus.BAD_REQUEST, "CLOTHES4001", "사이즈 정보가 하나 이상 존재해야 합니다."),
51+
ADDRESS_NOT_FOUND_FOR_MEETUP(HttpStatus.BAD_REQUEST, "CLOTHES4002", "직거래 시 주소 정보는 필수입니다."),
52+
4953
//계좌 관련
5054
ACCOUNT_NOT_FOUND(HttpStatus.NOT_FOUND, "ACCOUNT4001", "등록된 계좌 정보를 찾을 수 없습니다."),
5155

0 commit comments

Comments
 (0)