Skip to content

Commit

Permalink
기존 인수 보고서 통합 보고서 제출로 전환 및 개발 (#59)
Browse files Browse the repository at this point in the history
차량 wagger tag 수정
반납 보고서 API 개발
기존 인수 보고서 API 반납 보고서와 합쳐 보고서 API로 전환

 #50
  • Loading branch information
wcorn authored Aug 1, 2024
1 parent bde3b3d commit 46198f8
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -1,51 +1,68 @@
package kea.enter.enterbe.api.vehicle.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import kea.enter.enterbe.api.vehicle.service.VehicleService;
import kea.enter.enterbe.api.vehicle.service.dto.PostTakeVehicleReportServiceDto;
import kea.enter.enterbe.api.vehicle.service.dto.PostVehicleReportServiceDto;
import kea.enter.enterbe.domain.report.entity.VehicleReportType;
import kea.enter.enterbe.global.common.api.CustomResponseCode;
import kea.enter.enterbe.global.common.exception.CustomException;
import kea.enter.enterbe.global.common.exception.ResponseCode;
import kea.enter.enterbe.global.util.FileUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
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.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@Tag(name = "예제", description = "예제 API 명세서")
@Tag(name = "차량", description = "차량 API 명세서")
@RestController
@RequiredArgsConstructor
@RequestMapping("/vehicles")
@Validated
public class VehicleController {

private final VehicleService vehicleService;
private final FileUtil fileUtil;

@Operation(summary = "인수보고서 작성")
@PostMapping(value = "/reports/take", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE,
@Operation(summary = "보고서 작성")
@PostMapping(value = "/reports", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE,
MediaType.TEXT_PLAIN_VALUE})
public ResponseEntity<CustomResponseCode> postTakeVehicleReport(
@RequestPart(value = "front_img") MultipartFile front_img,
@RequestPart(value = "right_img") MultipartFile right_img,
@RequestPart(value = "back_img") MultipartFile back_img,
@RequestPart(value = "left_img") MultipartFile left_img,
@RequestPart(value = "dashboard_img") MultipartFile dashboardImg,
@RequestPart(value = "note") String note) {
@RequestPart(value = "note",required = false) String note,
@RequestPart(value = "parking_loc",required = false) String parkingLoc,
@RequestParam(name = "type") @NotNull(message = "보고서 종류를 입력해주세요")
@Schema(description = "보고서 종류 TAKE, RETURN", example = "TAKE")
VehicleReportType type
) {
//todo: spring security 구현 완료 시 token에서 memberId 값 가져오기
Long memberId = 1L;
if (!fileUtil.isImageFileList(
List.of(front_img, right_img, back_img, left_img, dashboardImg))) {
throw new CustomException(ResponseCode.NOT_IMAGE_FILE);
}
vehicleService.postTakeVehicleReport(
PostTakeVehicleReportServiceDto.of(memberId, front_img, right_img, back_img, left_img,
dashboardImg, note));
if(type.equals(VehicleReportType.RETURN) && !StringUtils.hasText(note)){
throw new CustomException(ResponseCode.NEED_PARKING_LOC_FOR_RETURN_REPORT);
}
vehicleService.postVehicleReport(
PostVehicleReportServiceDto.of(memberId, front_img, right_img, back_img, left_img,
dashboardImg, note, parkingLoc, type));
return ResponseEntity.ok(CustomResponseCode.SUCCESS);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package kea.enter.enterbe.api.vehicle.service;

import kea.enter.enterbe.api.vehicle.service.dto.PostTakeVehicleReportServiceDto;
import kea.enter.enterbe.api.vehicle.service.dto.PostVehicleReportServiceDto;

public interface VehicleService {

void postTakeVehicleReport(PostTakeVehicleReportServiceDto dto);
void postVehicleReport(PostVehicleReportServiceDto dto);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import kea.enter.enterbe.api.vehicle.service.dto.PostTakeVehicleReportServiceDto;
import kea.enter.enterbe.api.vehicle.service.dto.PostVehicleReportServiceDto;
import kea.enter.enterbe.domain.note.entity.VehicleNote;
import kea.enter.enterbe.domain.note.repository.VehicleNoteRepository;
import kea.enter.enterbe.domain.report.entity.VehicleReport;
import kea.enter.enterbe.domain.report.entity.VehicleReportType;
import kea.enter.enterbe.domain.report.repository.VehicleReportRepository;
import kea.enter.enterbe.domain.winning.entity.Winning;
import kea.enter.enterbe.domain.winning.entity.WinningState;
Expand All @@ -17,8 +18,10 @@
import kea.enter.enterbe.global.util.ObjectStorageUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.util.StringUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
Expand All @@ -34,9 +37,9 @@ public class VehicleServiceImpl implements VehicleService {
private final Clock clock;

@Override
public void postTakeVehicleReport(PostTakeVehicleReportServiceDto dto) {
public void postVehicleReport(PostVehicleReportServiceDto dto) {
List<String> images = new ArrayList<>();
Winning winning = findWinningByMemberIdAndTakeDate(dto.getMemberId(), LocalDate.now(clock));
Winning winning = getWinningByReportType(dto.getMemberId(), dto.getType());

try {
String frontImg = uploadS3Image(dto.getFrontImg());
Expand All @@ -49,20 +52,39 @@ public void postTakeVehicleReport(PostTakeVehicleReportServiceDto dto) {
images.add(leftImg);
String dashboardImg = uploadS3Image(dto.getDashboardImg());
images.add(dashboardImg);

VehicleReport vehicleReport = vehicleReportRepository.save(
VehicleReport.takeCreate(winning, frontImg, leftImg,
rightImg, backImg, dashboardImg));
vehicleNoteRepository.save(
VehicleNote.create(winning.getVehicle(), vehicleReport, dto.getNote()));
VehicleReport.create(winning, frontImg, leftImg,
rightImg, backImg, dashboardImg, dto.getParkingLoc(), dto.getType()));

if (StringUtils.hasText(dto.getNote())) {
vehicleNoteRepository.save(
VehicleNote.create(winning.getVehicle(), vehicleReport, dto.getNote()));
}

} catch (Exception e) {
deleteS3Images(images);
throw new CustomException(ResponseCode.INTERNAL_SERVER_ERROR);
}
}

private Winning findWinningByMemberIdAndTakeDate(Long memberId,LocalDate date) {
return winningRepository.findByMemberIdAndTakeDateAndState(memberId, date,WinningState.ACTIVE)
private Winning getWinningByReportType(Long memberId, VehicleReportType type) {
if (type.equals(VehicleReportType.TAKE)) {
return findWinningByMemberIdAndTakeDate(memberId, LocalDate.now(clock));
} else {
return findWinningByMemberIdAndReturnDate(memberId, LocalDate.now(clock));
}
}

private Winning findWinningByMemberIdAndReturnDate(Long memberId, LocalDate date) {
return winningRepository.findByMemberIdAndReturnDateAndState(memberId, date,
WinningState.ACTIVE)
.orElseThrow(() -> new CustomException(ResponseCode.WINNING_NOT_FOUND));
}

private Winning findWinningByMemberIdAndTakeDate(Long memberId, LocalDate date) {
return winningRepository.findByMemberIdAndTakeDateAndState(memberId, date,
WinningState.ACTIVE)
.orElseThrow(() -> new CustomException(ResponseCode.WINNING_NOT_FOUND));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package kea.enter.enterbe.api.vehicle.service.dto;

import java.util.List;
import kea.enter.enterbe.domain.report.entity.VehicleReportType;
import lombok.Builder;
import lombok.Getter;
import org.springframework.web.multipart.MultipartFile;

@Getter
public class PostTakeVehicleReportServiceDto {
public class PostVehicleReportServiceDto {

private Long memberId;
private MultipartFile frontImg;
Expand All @@ -15,30 +15,38 @@ public class PostTakeVehicleReportServiceDto {
private MultipartFile leftImg;
private MultipartFile dashboardImg;
private String note;
private String parkingLoc;
private VehicleReportType type;

@Builder
public PostTakeVehicleReportServiceDto(Long memberId, MultipartFile frontImg,
public PostVehicleReportServiceDto(Long memberId, MultipartFile frontImg,
MultipartFile rightImg, MultipartFile backImg, MultipartFile leftImg,
MultipartFile dashboardImg, String note) {
MultipartFile dashboardImg, String note, String parkingLoc,
VehicleReportType type) {
this.memberId = memberId;
this.frontImg = frontImg;
this.rightImg = rightImg;
this.backImg = backImg;
this.leftImg = leftImg;
this.dashboardImg = dashboardImg;
this.parkingLoc = parkingLoc;
this.type = type;
this.note = note;
}

public static PostTakeVehicleReportServiceDto of(Long memberId, MultipartFile frontImg,
public static PostVehicleReportServiceDto of(Long memberId, MultipartFile frontImg,
MultipartFile rightImg, MultipartFile backImg, MultipartFile leftImg,
MultipartFile dashboardImg, String note) {
return PostTakeVehicleReportServiceDto.builder()
MultipartFile dashboardImg, String note, String parkingLoc,
VehicleReportType type) {
return PostVehicleReportServiceDto.builder()
.memberId(memberId)
.frontImg(frontImg)
.rightImg(rightImg)
.backImg(backImg)
.leftImg(leftImg)
.dashboardImg(dashboardImg)
.parkingLoc(parkingLoc)
.type(type)
.note(note)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,18 @@ public static VehicleReport of(Winning winning, String frontImg, String leftImg,
.build();
}

public static VehicleReport takeCreate(Winning winning, String frontImg, String leftImg,
String rightImg, String backImg, String dashboardImg) {
public static VehicleReport create(Winning winning, String frontImg, String leftImg,
String rightImg, String backImg, String dashboardImg, String parkingLoc,
VehicleReportType type) {
return VehicleReport.builder()
.winning(winning)
.frontImg(frontImg)
.leftImg(leftImg)
.rightImg(rightImg)
.backImg(backImg)
.dashboardImg(dashboardImg)
.type(VehicleReportType.TAKE)
.parkingLoc(parkingLoc)
.type(type)
.state(VehicleReportState.ACTIVE)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

public enum VehicleReportType {
TAKE, RETURN
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,17 @@ Optional<Winning> findByMemberIdAndTakeDateAndState(
@Param("takeDate") LocalDate takeDate,
@Param("state") WinningState state
);

@Query(value = "SELECT w "
+ "FROM Winning w "
+ "left outer join w.apply a "
+ "left outer join a.applyRound ar "
+ "where a.member.id = :memberId "
+ "and ar.returnDate = :returnDate "
+ "and w.state = :state ")
Optional<Winning> findByMemberIdAndReturnDateAndState(
@Param("memberId") Long memberId,
@Param("returnDate") LocalDate returnDate,
@Param("state") WinningState state
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public enum ResponseCode {
VEHICLE_NOT_VALID("VHC_ERR_001", HttpStatus.NOT_FOUND, "법인 차량 정보를 찾을 수 없습니다."),
VEHICLE_NO_NOT_ALLOWED("VHC_ERR_002", HttpStatus.METHOD_NOT_ALLOWED, "유효하지 않은 차량번호 형식입니다."),
VEHICLE_DUPLICATED("VHC_ERR_003", HttpStatus.BAD_REQUEST, "이미 존재하는 차량입니다."),
NEED_PARKING_LOC_FOR_RETURN_REPORT("VHC-ERR-004",HttpStatus.BAD_REQUEST , "주차 위치를 입력해주세요."),
// PENALTY
PENALTY_NOT_FOUND("PEN-ERR-001", HttpStatus.NOT_FOUND, "페널티를 찾을 수 없습니다."),
//GLOBAL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,23 @@
import java.nio.charset.StandardCharsets;
import java.util.List;
import kea.enter.enterbe.ControllerTestSupport;
import kea.enter.enterbe.domain.report.entity.VehicleReportType;
import org.apache.hc.core5.http.ContentType;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockMultipartFile;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;


class VehicleControllerTest extends ControllerTestSupport {

@DisplayName(value = "")
@DisplayName(value = "보고서를 작성한다.")
@Test
public void postTakeVehicleReport() throws Exception {
public void postVehicleReport() throws Exception {
//given
MockMultipartFile image1 = new MockMultipartFile("front_img", "test.jpg",
ContentType.IMAGE_JPEG.getMimeType(),
Expand All @@ -39,14 +41,19 @@ public void postTakeVehicleReport() throws Exception {
given(fileUtil.isImageFileList(List.of(image1,image2,image3,image4,image5))).willReturn(true);
//when
mockMvc.perform(
multipart("/vehicles/reports/take")
multipart("/vehicles/reports")
.file(image1)
.file(image2)
.file(image3)
.file(image4)
.file(image5)
.file(notice)
).andExpect(status().isOk());
.file("note","note".getBytes())
.file("parking_loc","parking_loc".getBytes())
.param("type", VehicleReportType.TAKE.name())
)
.andDo(print())
.andExpect(status().isOk());
//then

}
Expand Down
Loading

0 comments on commit 46198f8

Please sign in to comment.