Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
Binary file modified .DS_Store
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import study.goorm.domain.cloth.domain.entity.Cloth;
import study.goorm.domain.member.domain.entity.Member;

import java.util.List;

public interface ClothRepository extends JpaRepository<Cloth, Long>{
// 1. wearNum 오름차순
Page<Cloth> findByMemberOrderByWearNumAsc(Member member, Pageable pageable);
Expand All @@ -18,4 +20,5 @@ public interface ClothRepository extends JpaRepository<Cloth, Long>{

// 4. createdAt 내림차순
Page<Cloth> findByMemberOrderByCreatedAtDesc(Member member, Pageable pageable);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package study.goorm.domain.history.api;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import study.goorm.domain.cloth.dto.ClothResponseDTO;
import study.goorm.domain.history.application.HistoryService;
import study.goorm.domain.history.dto.HistoryRequestDTO;
import study.goorm.domain.history.dto.HistoryResponseDTO;
import study.goorm.domain.member.domain.entity.Member;
import study.goorm.domain.model.enums.ClothSort;
import study.goorm.domain.model.exception.annotation.CheckPage;
import study.goorm.domain.model.exception.annotation.CheckPageSize;
import study.goorm.global.common.response.BaseResponse;
import study.goorm.global.error.code.status.SuccessStatus;
import study.goorm.domain.history.application.HistoryService;

import java.time.LocalDate;

@RestController
@RequiredArgsConstructor
@RequestMapping("/histories")
@Validated
public class HistoryRestController {
private final HistoryService historyService;

@GetMapping("/monthly")
@Operation(summary = "특정 회원의 월별 기록을 조회하는 API", description = "query string으로 clokeyId, month를 넘겨주세요.")
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "HISTORY_200", description = "OK, 월별 기록이 성공적으로 조회되었습니다."),
})
@Parameters({
@Parameter(name = "clokeyId", description = "클로키 유저의 clokey id, query string 입니다."),
@Parameter(name = "month", description = "월별 값, query string 입니다.")
})
public BaseResponse<HistoryResponseDTO.HistoryGetMonthly> getMonthlyHistories(
@RequestParam(value = "clokeyId") String clokeyId,
@RequestParam LocalDate month
) {
HistoryResponseDTO.HistoryGetMonthly result = historyService.getHistoryGetMonthly(clokeyId, month);

return BaseResponse.onSuccess(SuccessStatus.HISTORY_GET_MONTH, result);
}
@DeleteMapping("/{historyId}")
@Operation(summary = "특정 기록을 삭제하는 API", description = "path variable로 historyId를 넘겨주세요.")
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "HISTORY_202", description = "OK, 성공적으로 삭제되었습니다."),
})
@Parameters({
@Parameter(name = "historyId", description = "기록의 id, path variable 입니다.")
})
public BaseResponse<Void> deleteHistory(
@PathVariable(value = "historyId") Long historyId
) {

historyService.deleteHistory(historyId);

return BaseResponse.onSuccess(SuccessStatus.HISTORY_DELETED, null);
}

@PostMapping(value = "", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@Operation(summary = "새로운 옷 기록을 생성하는 API", description = "request body에 HistoryCreateRequest 형식의 데이터를 전달해주세요.")
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "HISTORY_201", description = "CREATED, 성공적으로 생성되었습니다."),
})
public BaseResponse<HistoryResponseDTO.HistoryCreateResult> createHistory(
@RequestPart("historyCreateRequest") HistoryRequestDTO.HistoryCreateRequest historyCreateRequest,
@RequestPart("imageFile") MultipartFile imageFile
) {
HistoryResponseDTO.HistoryCreateResult result = historyService.createHistory(historyCreateRequest,imageFile);

return BaseResponse.onSuccess(SuccessStatus.HISTORY_CREATED, result);
}

@PatchMapping(value = "/{historyId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@Operation(summary = "특정날짜 옷 기록을 수정하는 API", description = "path variable로 historyId를 넘겨주세요.")
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "HISTORY_203", description = "OK, 기록이 성공적으로 수정되었습니다."),
})
@Parameters({
@Parameter(name = "historyId", description = "기록의 id, path variable 입니다."),
})
public BaseResponse<ClothResponseDTO.ClothCreateResult> patchHistory(
@PathVariable Long historyId,
@RequestPart("historyUpdateRequest") @Valid HistoryRequestDTO.HistoryCreateRequest historyUpdateRequest,
@RequestPart(value = "imageFile", required = false) MultipartFile imageFile
) {
historyService.updateHistory(historyId, historyUpdateRequest, imageFile);

return BaseResponse.onSuccess(SuccessStatus.HISTORY_UPDATED, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package study.goorm.domain.history.application;

public interface HistoryImageQueryService {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package study.goorm.domain.history.application;

public class HistoryImageQueryServiceImpl {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package study.goorm.domain.history.application;

import org.springframework.web.multipart.MultipartFile;
import study.goorm.domain.history.dto.HistoryRequestDTO;
import study.goorm.domain.history.dto.HistoryResponseDTO;
import study.goorm.domain.member.domain.entity.Member;

import java.time.LocalDate;

public interface HistoryService {
HistoryResponseDTO.HistoryGetMonthly getHistoryGetMonthly(String clokeyId, LocalDate month);
void deleteHistory(Long historyId);
HistoryResponseDTO.HistoryCreateResult createHistory(HistoryRequestDTO.HistoryCreateRequest historyCreateResult, MultipartFile image);
HistoryResponseDTO.HistoryCreateResult updateHistory(Long historyId, HistoryRequestDTO.HistoryCreateRequest historyUpdateRequest, MultipartFile image);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package study.goorm.domain.history.application;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import study.goorm.domain.cloth.domain.entity.Cloth;
import study.goorm.domain.cloth.domain.repository.ClothRepository;
import study.goorm.domain.cloth.exception.ClothException;
import study.goorm.domain.history.converter.HistoryConverter;
import study.goorm.domain.history.domain.entity.History;
import study.goorm.domain.history.domain.entity.HistoryCloth;
import study.goorm.domain.history.domain.entity.HistoryImage;
import study.goorm.domain.history.domain.repository.HashtagHistoryRepository;
import study.goorm.domain.history.domain.repository.HistoryClothRepository;
import study.goorm.domain.history.domain.repository.HistoryImageRepository;
import study.goorm.domain.history.domain.repository.HistoryRepository;
import study.goorm.domain.history.dto.HistoryRequestDTO;
import study.goorm.domain.history.dto.HistoryResponseDTO;
import study.goorm.domain.history.exception.HistoryExeption;
import study.goorm.domain.member.domain.entity.Member;
import study.goorm.domain.member.domain.exception.MemberException;
import study.goorm.domain.member.domain.repository.MemberRepository;
import study.goorm.domain.model.enums.ClothSort;
import study.goorm.global.error.code.status.ErrorStatus;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class HistoryServiceImpl implements HistoryService {

private final HistoryRepository historyRepository;
private final HistoryImageRepository historyImageRepository;
private final MemberRepository memberRepository;
private final HashtagHistoryRepository hashtagHistoryRepository;
private final HistoryClothRepository historyClothRepository;
private final ClothRepository clothRepository;


@Override
@Transactional(readOnly = true)
public HistoryResponseDTO.HistoryGetMonthly getHistoryGetMonthly(String clokeyId, LocalDate month) {
Member member = memberRepository.findByClokeyId(clokeyId)
.orElseThrow(()-> new MemberException(ErrorStatus.NO_SUCH_MEMBER));

// 해당 월의 시작일과 마지막일 계산
LocalDate startOfMonth = month.withDayOfMonth(1);
LocalDate endOfMonth = month.withDayOfMonth(month.lengthOfMonth());

List<History> histories = historyRepository.findAllByMemberAndHistoryDateBetween(member, startOfMonth, endOfMonth);
List<Long> historyIds = histories.stream()
.map(History::getId)
.toList();
List<HistoryImage> historyImages = historyImageRepository.findAllByHistoryIdIn(historyIds);

return HistoryConverter.toHistoryGetMonthly(member, month, histories, historyImages);
}

@Override
@Transactional
public void deleteHistory(Long historyId) {
History history = historyRepository.findById(historyId)
.orElseThrow(()-> new HistoryExeption(ErrorStatus.NO_SUCH_HISTORY));

//매핑 테이블 삭제
hashtagHistoryRepository.deleteByHistory(history);
historyImageRepository.deleteByHistory(history);
historyClothRepository.deleteByHistory(history);

//최종 옷 삭제
historyRepository.delete(history);
}

@Override
@Transactional
public HistoryResponseDTO.HistoryCreateResult createHistory(HistoryRequestDTO.HistoryCreateRequest historyCreateResult, MultipartFile image) {
List<Cloth> cloth = clothRepository.findAllById(historyCreateResult.getClothes());
if (cloth.isEmpty()) {
throw new ClothException(ErrorStatus.NO_SUCH_CLOTH);
}


History newHistory = History.builder()
.historyDate(LocalDate.parse(historyCreateResult.getDate()))
.content(historyCreateResult.getContent())
.build();
HistoryImage newHistoryImage = HistoryImage.builder()
.history(newHistory)
.imageUrl("url")
.build();

historyImageRepository.save(newHistoryImage);


return HistoryConverter.toHistoryCreateResult(newHistory);
}

@Override
public HistoryResponseDTO.HistoryCreateResult updateHistory(Long historyId, HistoryRequestDTO.HistoryCreateRequest historyUpdateRequest, MultipartFile image) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package study.goorm.domain.history.converter;

import study.goorm.domain.history.domain.entity.History;
import study.goorm.domain.history.domain.entity.HistoryImage;
import study.goorm.domain.history.dto.HistoryResponseDTO;
import study.goorm.domain.member.domain.entity.Member;

import java.time.LocalDate;
import java.util.List;

public class HistoryConverter {

public static HistoryResponseDTO.HistoryGetMonthly toHistoryGetMonthly(Member member, LocalDate month, List<History> histories, List<HistoryImage> historyImages){
return HistoryResponseDTO.HistoryGetMonthly.builder()
.memberId(member.getId())
.nickName(member.getNickname())
.histories(toHistoryGetList(histories, historyImages))
.build();
}

private static List<HistoryResponseDTO.HistoryGet> toHistoryGetList(List<History> histories, List<HistoryImage> historyImages) {
return histories.stream()
.map(history -> {
HistoryImage image = historyImages.stream()
.filter(img -> img.getHistory().getId().equals(history.getId()))
.findFirst()
.orElse(null);
return toHistoryGet(history, image);
})
.collect(java.util.stream.Collectors.toList());
}

private static HistoryResponseDTO.HistoryGet toHistoryGet(History history, HistoryImage historyImage){
return HistoryResponseDTO.HistoryGet.builder()
.historyId(history.getId())
.date(history.getHistoryDate())
.imageUrl(historyImage != null ? historyImage.getImageUrl() : "비공개입니다")
.build();
}

public static HistoryResponseDTO.HistoryCreateResult toHistoryCreateResult(History history){
return HistoryResponseDTO.HistoryCreateResult.builder()
.historyId(history.getId())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import org.springframework.data.jpa.repository.JpaRepository;
import study.goorm.domain.history.domain.entity.HashtagHistory;
import study.goorm.domain.history.domain.entity.History;

public interface HashtagHistoryRepository extends JpaRepository<HashtagHistory, Long>{
void deleteByHistory(History history);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.data.jpa.repository.JpaRepository;
import study.goorm.domain.cloth.domain.entity.Cloth;
import study.goorm.domain.history.domain.entity.History;
import study.goorm.domain.history.domain.entity.HistoryCloth;

public interface HistoryClothRepository extends JpaRepository<HistoryCloth, Long>{
void deleteAllByCloth(Cloth cloth);
void deleteByHistory(History history);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package study.goorm.domain.history.domain.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import study.goorm.domain.history.domain.entity.History;
import study.goorm.domain.history.domain.entity.HistoryImage;

import java.util.List;

public interface HistoryImageRepository extends JpaRepository<HistoryImage, Long>{
List<HistoryImage> findAllByHistoryIdIn(List<Long> historyIds);
void deleteByHistory(History history);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import org.springframework.data.jpa.repository.JpaRepository;
import study.goorm.domain.history.domain.entity.History;
import study.goorm.domain.member.domain.entity.Member;

import java.time.LocalDate;
import java.util.List;

public interface HistoryRepository extends JpaRepository<History, Long>{
List<History> findAllByMemberAndHistoryDateBetween(Member member, LocalDate start, LocalDate end);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package study.goorm.domain.history.dto;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import study.goorm.domain.cloth.exception.annotation.CheckLowerUpperTempBound;
import study.goorm.domain.model.enums.Season;
import study.goorm.domain.model.enums.ThicknessLevel;

import java.util.List;

public class HistoryRequestDTO {

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class HistoryCreateRequest {

private String content;

private List<Long> clothes;

private List<String> hashtags;

private String date;
}
}
Loading