Skip to content

Commit

Permalink
feat/GH-143-voucher-use (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
inh2613 authored Jul 27, 2023
2 parents 63b8ff0 + 616f536 commit 0e52ba5
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 111 deletions.
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
package org.swmaestro.repl.gifthub.vouchers.controller;

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;
import org.springframework.beans.factory.annotation.Value;
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.bind.annotation.*;
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.dto.*;
import org.swmaestro.repl.gifthub.vouchers.service.StorageService;
import org.swmaestro.repl.gifthub.vouchers.service.VoucherService;

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;

@RestController
@RequestMapping("/vouchers")
Expand All @@ -47,8 +35,8 @@ public S3FileDto saveVoucherImage(@RequestPart("image_file") MultipartFile image
@PostMapping
@Operation(summary = "Voucher 등록 메서드", description = "클라이언트에서 요청한 기프티콘 정보를 저장하기 위한 메서드입니다.")
public VoucherSaveResponseDto saveVoucher(HttpServletRequest request,
@RequestBody VoucherSaveRequestDto voucherSaveRequestDto) throws
IOException {
@RequestBody VoucherSaveRequestDto voucherSaveRequestDto) throws
IOException {
String username = jwtProvider.getUsername(jwtProvider.resolveToken(request).substring(7));
return voucherService.save(username, voucherSaveRequestDto);
}
Expand All @@ -69,7 +57,15 @@ public List<VoucherReadResponseDto> listVoucher(HttpServletRequest request) {
@PatchMapping("/{voucherId}")
@Operation(summary = "Voucher 수정 메서드", description = "클라이언트에서 요청한 기프티콘 정보를 수정하기 위한 메서드입니다.")
public VoucherSaveResponseDto updateVoucher(@PathVariable Long voucherId,
@RequestBody VoucherUpdateRequestDto voucherUpdateRequestDto) throws IOException {
@RequestBody VoucherUpdateRequestDto voucherUpdateRequestDto) throws IOException {
return voucherService.update(voucherId, voucherUpdateRequestDto);
}

@PostMapping("/{voucherId}/usage")
@Operation(summary = "Voucher 사용 메서드", description = "클라이언트에서 요청한 기프티콘 사용 정보를 저장하기 위한 메서드입니다.")
public VoucherUseResponseDto useVoucher(HttpServletRequest request, @PathVariable Long voucherId,
@RequestBody VoucherUseRequestDto voucherUseRequestDto) throws IOException {
String username = jwtProvider.getUsername(jwtProvider.resolveToken(request).substring(7));
return voucherService.use(username, voucherId, voucherUseRequestDto);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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;


@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class VoucherUseRequestDto {
private Long id;
private int amount;
private String place;

@Builder
public VoucherUseRequestDto(Long id, int amount, String place) {
this.id = id;
this.amount = amount;
this.place = place;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class VoucherUseResponseDto {
private Long usageId;
private Long voucherId;
private int balance;

@Builder
public VoucherUseResponseDto(Long usageId, Long voucherId, int balance) {
this.usageId = usageId;
this.voucherId = voucherId;
this.balance = balance;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import java.util.List;

public interface VoucherRepository extends JpaRepository<Voucher, Long> {
List<Voucher> findByMemberUsername(String username);

List<Voucher> findByMemberUsernameAndBrandName(String username, String brandName);
List<Voucher> findAllByMemberUsername(String username);

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.swmaestro.repl.gifthub.vouchers.entity.VoucherUsageHistory;

import java.util.List;

public interface VoucherUsageHistoryRepository extends JpaRepository<VoucherUsageHistory, Long> {
List<VoucherUsageHistory> findAllByVoucherId(Long voucherId);
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
package org.swmaestro.repl.gifthub.vouchers.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.swmaestro.repl.gifthub.auth.service.MemberService;
import org.swmaestro.repl.gifthub.exception.BusinessException;
import org.swmaestro.repl.gifthub.exception.ErrorCode;
import org.swmaestro.repl.gifthub.util.DateConverter;
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.dto.*;
import org.swmaestro.repl.gifthub.vouchers.entity.Voucher;
import org.swmaestro.repl.gifthub.vouchers.entity.VoucherUsageHistory;
import org.swmaestro.repl.gifthub.vouchers.repository.VoucherRepository;
import org.swmaestro.repl.gifthub.vouchers.repository.VoucherUsageHistoryRepository;

import lombok.RequiredArgsConstructor;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
Expand All @@ -30,24 +30,25 @@ public class VoucherService {
private final ProductService productService;
private final VoucherRepository voucherRepository;
private final MemberService memberService;
private final VoucherUsageHistoryRepository voucherUsageHistoryRepository;

/*
기프티콘 저장 메서드
*/
public VoucherSaveResponseDto save(String username, VoucherSaveRequestDto voucherSaveRequestDto) throws
IOException {
IOException {
Voucher voucher = Voucher.builder()
.brand(brandService.read(voucherSaveRequestDto.getBrandName()))
.product(productService.read(voucherSaveRequestDto.getProductName()))
.barcode(voucherSaveRequestDto.getBarcode())
.expiresAt(DateConverter.stringToLocalDate(voucherSaveRequestDto.getExpiresAt()))
.imageUrl(storageService.getBucketAddress(voucherDirName) + voucherSaveRequestDto.getImageUrl())
.member(memberService.read(username))
.build();
.brand(brandService.read(voucherSaveRequestDto.getBrandName()))
.product(productService.read(voucherSaveRequestDto.getProductName()))
.barcode(voucherSaveRequestDto.getBarcode())
.expiresAt(DateConverter.stringToLocalDate(voucherSaveRequestDto.getExpiresAt()))
.imageUrl(storageService.getBucketAddress(voucherDirName) + voucherSaveRequestDto.getImageUrl())
.member(memberService.read(username))
.build();

return VoucherSaveResponseDto.builder()
.id(voucherRepository.save(voucher).getId())
.build();
.id(voucherRepository.save(voucher).getId())
.build();
}

/*
Expand All @@ -67,7 +68,7 @@ public VoucherReadResponseDto read(Long id) {
사용자 별 기프티콘 목록 조회 메서드
*/
public List<VoucherReadResponseDto> list(String username) {
List<Voucher> vouchers = voucherRepository.findByMemberUsername(username);
List<Voucher> vouchers = voucherRepository.findAllByMemberUsername(username);
if (vouchers == null) {
throw new BusinessException("존재하지 않는 사용자 입니다.", ErrorCode.NOT_FOUND_RESOURCE);
}
Expand All @@ -83,33 +84,86 @@ public List<VoucherReadResponseDto> list(String username) {
*/
public VoucherSaveResponseDto update(Long voucherId, VoucherUpdateRequestDto voucherUpdateRequestDto) {
Voucher voucher = voucherRepository.findById(voucherId)
.orElseThrow(() -> new BusinessException("존재하지 않는 상품권 입니다.", ErrorCode.NOT_FOUND_RESOURCE));
.orElseThrow(() -> new BusinessException("존재하지 않는 상품권 입니다.", ErrorCode.NOT_FOUND_RESOURCE));

voucher.setBarcode(
voucherUpdateRequestDto.getBarcode() == null ? voucher.getBarcode() : voucherUpdateRequestDto.getBarcode());
voucherUpdateRequestDto.getBarcode() == null ? voucher.getBarcode() : voucherUpdateRequestDto.getBarcode());
voucher.setBrand(voucherUpdateRequestDto.getBrandName() == null ? voucher.getBrand() :
brandService.read(voucherUpdateRequestDto.getBrandName()));
brandService.read(voucherUpdateRequestDto.getBrandName()));
voucher.setProduct(voucherUpdateRequestDto.getProductName() == null ? voucher.getProduct() :
productService.read(voucherUpdateRequestDto.getProductName()));
productService.read(voucherUpdateRequestDto.getProductName()));
voucher.setExpiresAt(voucherUpdateRequestDto.getExpiresAt() == null ? voucher.getExpiresAt() :
DateConverter.stringToLocalDate(voucherUpdateRequestDto.getExpiresAt()));
DateConverter.stringToLocalDate(voucherUpdateRequestDto.getExpiresAt()));

return VoucherSaveResponseDto.builder()
.id(voucherId)
.build();
.id(voucherId)
.build();
}

/*
기프티콘 사용 등록 메서드
*/
public VoucherUseResponseDto use(String username, Long voucherId, VoucherUseRequestDto voucherUseRequestDto) {
Optional<Voucher> voucher = voucherRepository.findById(voucherId);
List<Voucher> vouchers = voucherRepository.findAllByMemberUsername(username);
List<VoucherUsageHistory> voucherUsageHistories = voucherUsageHistoryRepository.findAllByVoucherId(voucherId);

if (voucher.isEmpty()) {
throw new BusinessException("존재하지 않는 상품권 입니다.", ErrorCode.NOT_FOUND_RESOURCE);
}
if (!vouchers.contains(voucher.get())) {
throw new BusinessException("상품권을 사용할 권한이 없습니다.", ErrorCode.ACCESS_DENIED);
}
int totalUsageAmount = voucherUsageHistories.stream()
.mapToInt(VoucherUsageHistory::getAmount)
.sum();

totalUsageAmount = Math.max(totalUsageAmount, 0);

if (totalUsageAmount == voucher.get().getBalance()) {
throw new BusinessException("이미 사용된 상품권 입니다.", ErrorCode.NOT_FOUND_RESOURCE);
}

int remainingBalance = voucher.get().getBalance() - totalUsageAmount;
int requestedAmount = voucherUseRequestDto.getAmount();

if (requestedAmount > remainingBalance) {
throw new BusinessException("잔액이 부족합니다.", ErrorCode.EXIST_RESOURCE);
}

if (voucher.get().getExpiresAt().isBefore(LocalDate.now())) {
throw new BusinessException("유효기간이 만료된 상품권 입니다.", ErrorCode.EXIST_RESOURCE);
}


VoucherUsageHistory voucherUsageHistory = VoucherUsageHistory.builder()
.member(memberService.read(username))
.voucher(voucher.get())
.amount(voucherUseRequestDto.getAmount())
.place(voucherUseRequestDto.getPlace())
.createdAt(LocalDateTime.now())
.build();

voucherUsageHistoryRepository.save(voucherUsageHistory);

return VoucherUseResponseDto.builder()
.usageId(voucherUsageHistory.getId())
.voucherId(voucherId)
.balance(remainingBalance - requestedAmount)
.build();
}

/*
Entity를 Dto로 변환하는 메서드
*/
public VoucherReadResponseDto mapToDto(Voucher voucher) {
VoucherReadResponseDto voucherReadResponseDto = VoucherReadResponseDto.builder()
.id(voucher.getId())
.barcode(voucher.getBarcode())
.expiresAt(voucher.getExpiresAt().toString())
.product(voucher.getProduct())
.username(voucher.getMember().getUsername())
.build();
.id(voucher.getId())
.barcode(voucher.getBarcode())
.expiresAt(voucher.getExpiresAt().toString())
.product(voucher.getProduct())
.username(voucher.getMember().getUsername())
.build();
return voucherReadResponseDto;
}
}
Loading

0 comments on commit 0e52ba5

Please sign in to comment.