Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package study.goorm.domain.cloth.api;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import study.goorm.domain.cloth.application.ClothService;
import study.goorm.domain.cloth.dto.ClothResponseDTO;
import study.goorm.global.common.response.BaseResponse;
import study.goorm.global.error.code.status.SuccessStatus;

@RestController
@RequiredArgsConstructor
@RequestMapping("/cloth-")
@Validated
public class ClothRestController {

private final ClothService clothService;

@GetMapping("/{cloth-id}/edit-view")
@Operation(summary = "특정 Cloth에 대한 정보를 수정용으로 조회하는 API", description = "Path Variable로 clothId를 던져주세요.")
@ApiResponse({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "CLOTH_200", description = "OK, 성공적으로 조회되었습니다."),
}) public BaseResponse<ClothResponseDTO.ClothEditViewResult>(
@PathVariable(name = "cloth-id") Long clothId
) {
ClothResponseDTO.ClothEditViewResult result = clothService.getClothEditView(clothId);

return BaseResponse.onSuccess(SuccessStatus.CLOTH_VIEW_SUCCESS, result);

}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package study.goorm.domain.cloth.application;

import study.goorm.domain.cloth.domain.entity.Cloth;

import java.util.Map;

public interface ClothImageQueryService {
Map<Long, String> getFirstImageUrlMap(Iterable<Cloth> clothes);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package study.goorm.domain.cloth.application;

import study.goorm.domain.cloth.domain.entity.Cloth;
import study.goorm.domain.cloth.domain.entity.ClothImage;
import study.goorm.domain.cloth.domain.repository.ClothImageRepository;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

public class ClothImageQueryServicelmpl implements ClothImageQueryService{
private final ClothImageRepository clothImageRepository;

@Override
public Map<Long, String> getFirstImageUrlMap(Iterable<Cloth> clothes) {
List<Long> clothIds = StreamSupport.stream(clothes.spliterator(), false)
.map(Cloth::getId)
.toList();

// cloth_id 기준으로 첫 이미지만 가져오는 쿼리 (IN 절 + group by 또는 distinct 필요)
List<ClothImage> firstImages = clothImageRepository.findFirstImagesByClothIds(clothIds);

return firstImages.stream()
.collect(Collectors.toMap(
image -> image.getCloth().getId(),
ClothImage::getImageUrl
));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package study.goorm.domain.cloth.application;

import org.springframework.web.multipart.MultipartFile;
import study.goorm.domain.cloth.dto.ClothRequestDTO;
import study.goorm.domain.cloth.dto.ClothResponseDTO;
import study.goorm.domain.model.Enum.ClothSort;

public interface ClothService {
ClothResponseDTO.ClothEditViewResult getClothEditView(Long clothId);
ClothResponseDTO.MemberCloseResult getMemberCloset(String clokeyId, ClothSort sort, int page, int size);
ClothResponseDTO.ClothCreateResult createCloth(ClothRequestDTO.ClothCreateRequest clothCreateResult, MultipartFile image);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package study.goorm.domain.cloth.application;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import study.goorm.domain.cloth.converter.ClothConverter;
import study.goorm.domain.cloth.domain.entity.Category;
import study.goorm.domain.cloth.domain.entity.Cloth;
import study.goorm.domain.cloth.domain.entity.ClothImage;
import study.goorm.domain.cloth.domain.repository.ClothImageRepository;
import study.goorm.domain.cloth.domain.repository.ClothRepository;
import study.goorm.domain.cloth.dto.ClothRequestDTO;
import study.goorm.domain.cloth.dto.ClothResponseDTO;
import study.goorm.domain.cloth.exception.ClothException;
import study.goorm.domain.member.domain.entity.Member;
import study.goorm.domain.member.domain.exception.MemberException;
import study.goorm.domain.model.Enum.ClothSort;
import study.goorm.global.error.code.status.ErrorStatus;

import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class ClothServicelmpl implements ClothService {
private final ClothRepository clothRepository;
private final ClothImageRepository clothImageRepository;

@Override
@Transactional(readOnly = true)
public ClothResponseDTO.ClothEditViewResult getClothEditView(Long clothId) {

Cloth cloth = clothRepository.findById(clothId).orElseThrow(()-> new ClothException(ErrorStatus.NO_SUCH_CLOTH));
List<ClothImage> clothImageUrls = clothImageRepository.findAllByCloth(cloth);

String firstImageUrl = clothImageUrls.stream()
.findFirst()
.map(ClothImage::getImageUrl)
.orElseThrow(() -> new ClothException(ErrorStatus.NO_ClOTH_IMAGE));

return ClothConverter.toClothEditViewResult(cloth, clothImageUrl);
}

@Override
public ClothResponseDTO.MemberCloseResult getMemberCloset(String clokeyId, ClothSort sort, int page, int size) {
return null;
}

@Override
@Transactional
public ClothResponseDTO.ClothCreateResult createCloth(ClothRequestDTO.ClothCreateRequest clothCreateResult, MultipartFile image) {

Member member = memberRepository.findById(clothCreateResult.getMemberId())
.orElseThrow(()-> new MemberException(ErrorStatus.NO_SUCH_MEMBER));

Category category = categoryRepository.findById(clothCreateResult.getCategoryId())
.orElseThrow(()-> new ClothException(ErrorStatus.NO_SUCH_CATEGORY));

Cloth newCloth = Cloth.builder()
.name(clothCreateResult.getName())
.wearNum(0)
.season(clothCreateResult.getSeasons())
.tempUpperBound(clothCreateResult.getTempUpperBound())
.tempLowerBound(clothCreateResult.getTempLowerBound())
.thicknessLevel(clothCreateResult.getThicknessLevel())
.clothUrl(clothCreateResult.getClothUrl())
.brand(clothCreateResult.getBrand())
.category(category)
.member(member)
.build();

clothRepository.save(newCloth);

ClothImage newClothImage = ClothImage.builder()
.cloth(newCloth)
.imageUrl("아직 S3를 구현하지 않아서 url이 없어용")
.build();

clothImageRepository.save(newClothImage);

return ClothConverter.toClothCreateResult(newCloth);
}






}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package study.goorm.domain.cloth.converter;

import lombok.Getter;
import study.goorm.domain.cloth.domain.entity.Cloth;
import study.goorm.domain.cloth.dto.ClothResponseDTO;

@Getter
public class ClothConverter {
public static ClothResponseDTO.ClothEditViewResult toClothEditViewResult(Cloth cloth, String clothImageUrl) {
return ClothResponseDTO.ClothEditViewResult.builder()
.id(cloth.getId())
.brand(cloth.getBrand())
.categoryId(cloth.getCategory().getId())
.clothUrl(cloth.getClothUrl())
.imageUrl(clothImageUrl)
.name(cloth.getName())
.seasons(cloth.getSeason())
.tempLowerBound(cloth.getTempLowerBound())
.tempUpperBound(cloth.getTempUpperBound())
.thicknessLevel(cloth.getThicknessLevel())
.build();
}


public static ClothResponseDTO.ClothCreateResult toClothCreateResult(Cloth cloth){
return ClothResponseDTO.ClothCreateResult.builder()
.id(cloth.getId())
.build();
}
}
48 changes: 48 additions & 0 deletions src/main/java/study/goorm/domain/cloth/dto/ClothRequestDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package study.goorm.domain.cloth.dto;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
import study.goorm.domain.cloth.exception.annotation.CheckLowerUpperTempBound;
import study.goorm.domain.model.Enum.Season;
import study.goorm.domain.model.Enum.ThicknessLevel;

import java.util.List;


public class ClothRequestDTO {
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@CheckLowerUpperTempBound
public static class ClothCreateRequest {
private Long memberId;

private Long categoryId;

private String name;

private List<Season> seasons;

@Max(40)
@Min(-20)
private Integer tempUpperBound;

@Max(40)
@Min(-20)
private Integer tempLowerBound;

private ThicknessLevel thicknessLevel;

private String clothUrl;

private String brand;

}

}
45 changes: 45 additions & 0 deletions src/main/java/study/goorm/domain/cloth/dto/ClothResponseDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package study.goorm.domain.cloth.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import study.goorm.domain.model.Enum.Season;
import study.goorm.domain.model.Enum.ThicknessLevel;

import java.util.List;

@Getter
public class ClothResponseDTO {

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ClothCreateResult {
private Long id;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ClothEditViewResult {
private Long id;
private String name;
private List<Season> seasons;
private int tempUpperBound;
private int tempLowerBound;
private ThicknessLevel thicknessLevel;
private String clothUrl;
private String brand;
private String imageUrl;
private Long categoryId;
}


public class MemberCloseResult{

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package study.goorm.domain.cloth.exception;

import study.goorm.global.error.code.BaseErrorCode;
import study.goorm.global.exception.GeneralException;

public class ClothException extends GeneralException {
public ClothException(BaseErrorCode code) {
super(code);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package study.goorm.domain.cloth.exception.annotation;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import study.goorm.domain.cloth.exception.validator.CheckLowerUpperTempBoundValidator;

import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = CheckLowerUpperTempBoundValidator.class)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckLowerUpperTempBound {
String message() default "상한 온도는 하한 온도보다 높아야 합니다.";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package study.goorm.domain.cloth.exception.validator;

import jakarta.validation.ConstraintValidator;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import study.goorm.domain.cloth.dto.ClothRequestDTO;
import study.goorm.domain.cloth.exception.annotation.CheckLowerUpperTempBound;

@Component
@RequiredArgsConstructor
public class CheckLowerUpperTempBoundValidator {

@Override
public void initialize(CheckLowerUpperTempBound constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}

@Override
public boolean isValid(ClothRequestDTO.ClothCreateRequest request, ConstraintValidatorContext context) {
boolean isValid = request.getTempLowerBound() <= request.getTempUpperBound();

if (!isValid) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(ErrorStatus.LOWER_TEMP_BIGGER_THAN_UPPER_TEMP.toString()).addConstraintViolation();
}

return isValid;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package study.goorm.domain.member.domain.exception;

import study.goorm.global.error.code.BaseErrorCode;
import study.goorm.global.exception.GeneralException;

public class MemberException extends GeneralException {
public MemberException(BaseErrorCode code) {
super(code);
}
}
12 changes: 12 additions & 0 deletions src/main/java/study/goorm/domain/model/Enum/ClothSort.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package study.goorm.domain.model.Enum;

public enum ClothSort {
//착용순
WEAR,
//미착용순
NOT_WEAR,
//최신 등록순
LATEST,
//오래된 순
OLDEST
}
Loading