diff --git a/src/main/java/org/swmaestro/repl/gifthub/vouchers/controller/VoucherController.java b/src/main/java/org/swmaestro/repl/gifthub/vouchers/controller/VoucherController.java index bef723ee..cd82fb24 100644 --- a/src/main/java/org/swmaestro/repl/gifthub/vouchers/controller/VoucherController.java +++ b/src/main/java/org/swmaestro/repl/gifthub/vouchers/controller/VoucherController.java @@ -1,22 +1,31 @@ package org.swmaestro.repl.gifthub.vouchers.controller; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.servlet.http.HttpServletRequest; -import lombok.RequiredArgsConstructor; +import java.io.IOException; +import java.util.List; + import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import org.swmaestro.repl.gifthub.util.JwtProvider; import org.swmaestro.repl.gifthub.vouchers.dto.S3FileDto; import org.swmaestro.repl.gifthub.vouchers.dto.VoucherReadResponseDto; import org.swmaestro.repl.gifthub.vouchers.dto.VoucherSaveRequestDto; import org.swmaestro.repl.gifthub.vouchers.dto.VoucherSaveResponseDto; +import org.swmaestro.repl.gifthub.vouchers.dto.VoucherUpdateRequestDto; import org.swmaestro.repl.gifthub.vouchers.service.StorageService; import org.swmaestro.repl.gifthub.vouchers.service.VoucherService; -import java.io.IOException; -import java.util.List; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; @RestController @RequestMapping("/vouchers") @@ -37,8 +46,9 @@ public S3FileDto saveVoucherImage(@RequestPart("image_file") MultipartFile image @PostMapping @Operation(summary = "Voucher 등록 메서드", description = "클라이언트에서 요청한 기프티콘 정보를 저장하기 위한 메서드입니다.") - public VoucherSaveResponseDto saveVoucher(HttpServletRequest request, @RequestBody VoucherSaveRequestDto voucherSaveRequestDto) throws - IOException { + public VoucherSaveResponseDto saveVoucher(HttpServletRequest request, + @RequestBody VoucherSaveRequestDto voucherSaveRequestDto) throws + IOException { String username = jwtProvider.getUsername(jwtProvider.resolveToken(request).substring(7)); return voucherService.save(username, voucherSaveRequestDto); } @@ -55,4 +65,11 @@ public List listVoucher(HttpServletRequest request) { String username = jwtProvider.getUsername(jwtProvider.resolveToken(request).substring(7)); return voucherService.list(username); } + + @PatchMapping("/{voucherId}") + @Operation(summary = "Voucher 수정 메서드", description = "클라이언트에서 요청한 기프티콘 정보를 수정하기 위한 메서드입니다.") + public VoucherSaveResponseDto updateVoucher(@PathVariable Long voucherId, + @RequestBody VoucherUpdateRequestDto voucherUpdateRequestDto) throws IOException { + return voucherService.update(voucherId, voucherUpdateRequestDto); + } } \ No newline at end of file diff --git a/src/main/java/org/swmaestro/repl/gifthub/vouchers/dto/VoucherUpdateRequestDto.java b/src/main/java/org/swmaestro/repl/gifthub/vouchers/dto/VoucherUpdateRequestDto.java new file mode 100644 index 00000000..4f8bc6a0 --- /dev/null +++ b/src/main/java/org/swmaestro/repl/gifthub/vouchers/dto/VoucherUpdateRequestDto.java @@ -0,0 +1,29 @@ +package org.swmaestro.repl.gifthub.vouchers.dto; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@ToString +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class VoucherUpdateRequestDto { + private String barcode; + private String expiresAt; + private String productName; + private String brandName; + + @Builder + public VoucherUpdateRequestDto(String barcode, String expiresAt, String productName, String brandName) { + this.barcode = barcode; + this.expiresAt = expiresAt; + this.productName = productName; + this.brandName = brandName; + } +} diff --git a/src/main/java/org/swmaestro/repl/gifthub/vouchers/entity/Voucher.java b/src/main/java/org/swmaestro/repl/gifthub/vouchers/entity/Voucher.java index 59a81c04..5c3804c0 100644 --- a/src/main/java/org/swmaestro/repl/gifthub/vouchers/entity/Voucher.java +++ b/src/main/java/org/swmaestro/repl/gifthub/vouchers/entity/Voucher.java @@ -16,9 +16,11 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; @Entity @Getter +@Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Voucher extends BaseTimeEntity { @Id diff --git a/src/main/java/org/swmaestro/repl/gifthub/vouchers/service/VoucherService.java b/src/main/java/org/swmaestro/repl/gifthub/vouchers/service/VoucherService.java index 5391addb..07e142d8 100644 --- a/src/main/java/org/swmaestro/repl/gifthub/vouchers/service/VoucherService.java +++ b/src/main/java/org/swmaestro/repl/gifthub/vouchers/service/VoucherService.java @@ -14,6 +14,7 @@ import org.swmaestro.repl.gifthub.vouchers.dto.VoucherReadResponseDto; import org.swmaestro.repl.gifthub.vouchers.dto.VoucherSaveRequestDto; import org.swmaestro.repl.gifthub.vouchers.dto.VoucherSaveResponseDto; +import org.swmaestro.repl.gifthub.vouchers.dto.VoucherUpdateRequestDto; import org.swmaestro.repl.gifthub.vouchers.entity.Voucher; import org.swmaestro.repl.gifthub.vouchers.repository.VoucherRepository; @@ -77,6 +78,27 @@ public List list(String username) { return voucherReadResponseDtos; } + /* + 기프티콘 정보 수정 메서드 + */ + public VoucherSaveResponseDto update(Long voucherId, VoucherUpdateRequestDto voucherUpdateRequestDto) { + Voucher voucher = voucherRepository.findById(voucherId) + .orElseThrow(() -> new BusinessException("존재하지 않는 상품권 입니다.", ErrorCode.NOT_FOUND_RESOURCE)); + + voucher.setBarcode( + voucherUpdateRequestDto.getBarcode() == null ? voucher.getBarcode() : voucherUpdateRequestDto.getBarcode()); + voucher.setBrand(voucherUpdateRequestDto.getBrandName() == null ? voucher.getBrand() : + brandService.read(voucherUpdateRequestDto.getBrandName())); + voucher.setProduct(voucherUpdateRequestDto.getProductName() == null ? voucher.getProduct() : + productService.read(voucherUpdateRequestDto.getProductName())); + voucher.setExpiresAt(voucherUpdateRequestDto.getExpiresAt() == null ? voucher.getExpiresAt() : + DateConverter.stringToLocalDate(voucherUpdateRequestDto.getExpiresAt())); + + return VoucherSaveResponseDto.builder() + .id(voucherId) + .build(); + } + /* Entity를 Dto로 변환하는 메서드 */ diff --git a/src/test/java/org/swmaestro/repl/gifthub/vouchers/controller/VoucherControllerTest.java b/src/test/java/org/swmaestro/repl/gifthub/vouchers/controller/VoucherControllerTest.java index 4d60b85d..1544fb8c 100644 --- a/src/test/java/org/swmaestro/repl/gifthub/vouchers/controller/VoucherControllerTest.java +++ b/src/test/java/org/swmaestro/repl/gifthub/vouchers/controller/VoucherControllerTest.java @@ -1,6 +1,13 @@ package org.swmaestro.repl.gifthub.vouchers.controller; -import com.fasterxml.jackson.databind.ObjectMapper; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.ArrayList; +import java.util.List; + import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -13,16 +20,10 @@ import org.swmaestro.repl.gifthub.vouchers.dto.VoucherReadResponseDto; import org.swmaestro.repl.gifthub.vouchers.dto.VoucherSaveRequestDto; import org.swmaestro.repl.gifthub.vouchers.dto.VoucherSaveResponseDto; +import org.swmaestro.repl.gifthub.vouchers.dto.VoucherUpdateRequestDto; import org.swmaestro.repl.gifthub.vouchers.service.VoucherService; -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.fasterxml.jackson.databind.ObjectMapper; @SpringBootTest @AutoConfigureMockMvc @@ -44,16 +45,16 @@ class VoucherControllerTest { void saveVoucher() throws Exception { // given VoucherSaveRequestDto voucher = VoucherSaveRequestDto.builder() - .brandName("스타벅스") - .productName("아이스 아메리카노 T") - .barcode("012345678910") - .expiresAt("2023-06-15") - .imageUrl("https://s3.ap-northeast-2.amazonaws.com/gifthub-voucher/1623777600000_스타벅스_아이스아메리카노T.png") - .build(); + .brandName("스타벅스") + .productName("아이스 아메리카노 T") + .barcode("012345678910") + .expiresAt("2023-06-15") + .imageUrl("https://s3.ap-northeast-2.amazonaws.com/gifthub-voucher/1623777600000_스타벅스_아이스아메리카노T.png") + .build(); VoucherSaveResponseDto voucherSaveResponseDto = VoucherSaveResponseDto.builder() - .id(1L) - .build(); + .id(1L) + .build(); // when when(jwtProvider.resolveToken(any())).thenReturn("my_awesome_access_token"); @@ -62,10 +63,10 @@ void saveVoucher() throws Exception { // then mockMvc.perform(post("/vouchers") - .header("Authorization", "Bearer my_awesome_access_token") - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(voucher))) - .andExpect(status().isOk()); + .header("Authorization", "Bearer my_awesome_access_token") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(voucher))) + .andExpect(status().isOk()); } /* @@ -76,10 +77,10 @@ void readVoucherTest() throws Exception { // given Long voucherId = 1L; VoucherReadResponseDto voucherReadResponseDto = VoucherReadResponseDto.builder() - .id(1L) - .barcode("012345678910") - .expiresAt("2023-06-15") - .build(); + .id(1L) + .barcode("012345678910") + .expiresAt("2023-06-15") + .build(); when(voucherService.read(voucherId)).thenReturn(voucherReadResponseDto); //when @@ -100,23 +101,54 @@ void listVoucherTest() throws Exception { List voucherReadResponseDtos = new ArrayList<>(); voucherReadResponseDtos.add(VoucherReadResponseDto.builder() - .id(1L) - .barcode("012345678910") - .expiresAt("2023-06-15") - .build()); + .id(1L) + .barcode("012345678910") + .expiresAt("2023-06-15") + .build()); voucherReadResponseDtos.add(VoucherReadResponseDto.builder() - .id(2L) - .barcode("012345678911") - .expiresAt("2023-06-16") - .build()); - + .id(2L) + .barcode("012345678911") + .expiresAt("2023-06-16") + .build()); + when(jwtProvider.resolveToken(any())).thenReturn(accessToken); when(jwtProvider.getUsername(anyString())).thenReturn(username); when(voucherService.list(username)).thenReturn(voucherReadResponseDtos); mockMvc.perform(get("/vouchers") - .header("Authorization", "Bearer " + accessToken)) - .andExpect(status().isOk()); + .header("Authorization", "Bearer " + accessToken)) + .andExpect(status().isOk()); + } + + /* + 기프티콘 정보 수정 테스트 + */ + @Test + @WithMockUser(username = "이진우", roles = "USER") + void voucherUpdateTest() throws Exception { + // given + VoucherUpdateRequestDto voucherUpdateRequestDto = VoucherUpdateRequestDto.builder() + .brandName("스타벅스") + .productName("아이스 아메리카노 T") + .barcode("012345678910") + .expiresAt("2023-06-15") + .build(); + + VoucherSaveResponseDto voucherSaveResponseDto = VoucherSaveResponseDto.builder() + .id(1L) + .build(); + + // when + when(jwtProvider.resolveToken(any())).thenReturn("my_awesome_access_token"); + when(jwtProvider.getUsername(anyString())).thenReturn("이진우"); + when(voucherService.update(any(), any(VoucherUpdateRequestDto.class))).thenReturn(voucherSaveResponseDto); + + // then + mockMvc.perform(patch("/vouchers/1") + .header("Authorization", "Bearer my_awesome_access_token") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(voucherSaveResponseDto))) + .andExpect(status().isOk()); } } \ No newline at end of file