Skip to content

Commit

Permalink
[#5] 응모 API 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
gugbab2 committed Jan 6, 2025
1 parent 75546ca commit 1facfa4
Show file tree
Hide file tree
Showing 17 changed files with 359 additions and 229 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.gugbab2.productdraw.controller;

import com.gugbab2.productdraw.domain.entity.Draw;
import com.gugbab2.productdraw.domain.entity.Entrant;
import com.gugbab2.productdraw.domain.entity.Payment;
import com.gugbab2.productdraw.domain.service.DrawService;
import com.gugbab2.productdraw.dto.DrawDto;
import com.gugbab2.productdraw.dto.PaymentDto;
import com.gugbab2.productdraw.exception.EntrantNotFoundException;
import com.gugbab2.productdraw.exception.ProductNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/draws")
@RequiredArgsConstructor
public class DrawController {

private final DrawService drawService;

// 응모 제출
@PostMapping("/submit")
public ResponseEntity<?> createDraw(@RequestBody DrawDto.CreateDrawDto drawDto) {
try {
Draw entry = drawService.createDraw(drawDto.getEntrantId(), drawDto.getProductId());
return new ResponseEntity<>(entry, HttpStatus.CREATED);
} catch (EntrantNotFoundException | ProductNotFoundException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
}
}

// 응모 결과 발표
@PostMapping("/{productId}result")
public ResponseEntity<List<Entrant>> announceWinners(@PathVariable String productId) {
List<Entrant> entrants = drawService.announceResult(productId);
return new ResponseEntity<>(entrants, HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.gugbab2.productdraw.domain.entity;

import com.gugbab2.productdraw.domain.vo.WinnerStatus;
import lombok.Getter;
import lombok.Setter;

import java.util.UUID;

@Getter
@Setter
public class Draw {
private String id;
private String entrantId;
private String productId;
private boolean isPaid;
private WinnerStatus winnerStatus;

public Draw(String entrantId, String productId) {
this.id = UUID.randomUUID().toString();
this.entrantId = entrantId;
this.productId = productId;
this.isPaid = false;
this.winnerStatus = WinnerStatus.PENDING; // PENDING : 대기
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.gugbab2.productdraw.domain.entity;

import lombok.Getter;
import lombok.Setter;

import java.util.UUID;

@Getter
@Setter
public class Entrant {
private String id;
private String shippingAddress;
private String paymentMethod;

public Entrant(String shippingAddress, String paymentMethod) {
this.id = UUID.randomUUID().toString();
this.shippingAddress = shippingAddress;
this.paymentMethod = paymentMethod;
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ public class Product {
private double price;
private String size;
private String category;
private boolean isDone;
private int stock;

public Product(String id, String name, double price, String size, String category) {
this.id = id;
public Product(String name, double price, String size, String category, int stock) {
this.id = UUID.randomUUID().toString();
this.name = name;
this.price = price;
this.size = size;
this.category = category;
this.isDone = false;
this.stock = stock;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.gugbab2.productdraw.domain.repository;

import com.gugbab2.productdraw.domain.entity.Draw;

import java.util.List;

public interface DrawRepository {
Draw save(Draw entry);
Draw findById(String id);
List<Draw> findByProductId(String productId);
List<Draw> findByEntrantId(String entrantId);
void updateById(Draw draw);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.gugbab2.productdraw.domain.repository;

import com.gugbab2.productdraw.domain.entity.Entrant;

public interface EntrantRepository {

Entrant findById(String id);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.gugbab2.productdraw.domain.repository.inmemory;

import com.gugbab2.productdraw.domain.entity.Draw;
import com.gugbab2.productdraw.domain.entity.Entrant;
import com.gugbab2.productdraw.domain.repository.DrawRepository;
import com.gugbab2.productdraw.domain.vo.WinnerStatus;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository
public class DrawRepositoryImpl implements DrawRepository {
private final Map<String, Draw> entryDatabase = new HashMap<>();

@Override
public Draw save(Draw draw) {
entryDatabase.put(draw.getId(), draw);
return draw;
}

@Override
public Draw findById(String drawId) {
return entryDatabase.get(drawId);
}

@Override
public List<Draw> findByProductId(String productId) {
List<Draw> result = new ArrayList<>();
for (Draw draw : entryDatabase.values()) {
if (productId.equals(draw.getProductId())) {
result.add(draw);
}
}
return result;
}

@Override
public List<Draw> findByEntrantId(String entrantId) {
List<Draw> result = new ArrayList<>();
for (Draw draw : entryDatabase.values()) {
if (entrantId.equals(draw.getEntrantId())) {
result.add(draw);
}
}
return result;
}

@Override
public void updateById(Draw draw) {
Draw existingDraw = entryDatabase.get(draw.getId());

if (existingDraw != null) {
existingDraw.setWinnerStatus(WinnerStatus.WINNER);

entryDatabase.put(draw.getId(), existingDraw);
} else {
throw new IllegalArgumentException("Draw not found with id: " + draw.getId());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.gugbab2.productdraw.domain.repository.inmemory;

import com.gugbab2.productdraw.domain.entity.Entrant;
import com.gugbab2.productdraw.domain.repository.EntrantRepository;
import org.springframework.stereotype.Repository;

import java.util.HashMap;
import java.util.Map;

@Repository
public class EntrantRepositoryImpl implements EntrantRepository {
private final Map<String, Entrant> entrantDatabase = new HashMap<>();

@Override
public Entrant findById(String id) {
return entrantDatabase.get(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.gugbab2.productdraw.domain.service;

import com.gugbab2.productdraw.domain.entity.Draw;
import com.gugbab2.productdraw.domain.entity.Entrant;
import com.gugbab2.productdraw.domain.entity.Product;
import com.gugbab2.productdraw.domain.repository.inmemory.DrawRepositoryImpl;
import com.gugbab2.productdraw.domain.repository.inmemory.EntrantRepositoryImpl;
import com.gugbab2.productdraw.domain.repository.inmemory.ProductRepositoryImpl;
import com.gugbab2.productdraw.exception.DrawNotFoundException;
import com.gugbab2.productdraw.exception.EntrantNotFoundException;
import com.gugbab2.productdraw.exception.ProductNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@RequiredArgsConstructor
public class DrawService {

private final DrawRepositoryImpl drawRepository;
private final EntrantRepositoryImpl entrantRepository;
private final ProductRepositoryImpl productRepository;

/**
* 응모 생성
*
* @param entrantId
* @param productId
* @return
*/
public Draw createDraw(String entrantId, String productId) {

Entrant entrant = entrantRepository.findById(entrantId);
// 사용자 중복 요청 예외처리
if(entrant == null) {
throw new EntrantNotFoundException(entrantId);
}

Product product = productRepository.findById(productId);
// 상품 미조회 예외처리
if(product == null) {
throw new ProductNotFoundException(productId);
}

// 응모 생성
Draw draw = new Draw(entrantId, productId);
return drawRepository.save(draw);
}

/**
* 응모 당첨자 생성
*
* @param productId
* @return
*/
public List<Entrant> announceResult(String productId) {

Product product = productRepository.findById(productId);
// 상품 미조회 예외처리
if (product == null) {
throw new ProductNotFoundException(productId);
}

// 상품에 대한 모든 응모자 조회
List<Draw> draws = drawRepository.findByProductId(productId);
if (draws == null || draws.isEmpty()) {
throw new DrawNotFoundException(productId);
}

// 응모자 목록에서 Entrant 객체 추출
List<Entrant> entrants = new ArrayList<>();
for (Draw draw : draws) {
Entrant entrant = entrantRepository.findById(draw.getEntrantId());
if (entrant != null) {
entrants.add(entrant);
}
}

// 응모자 중 재고 만큼 당첨자를 선정해
int stockCount = product.getStock();
int winnerCount = Math.min(entrants.size(), stockCount);
List<Entrant> winners = pickRandomWinners(entrants, winnerCount);

// 당첨 결과를 업데이트 해줘
for (Entrant winner : winners) {
List<Draw> winnerDraws = drawRepository.findByEntrantId(winner.getId());
for(Draw draw : winnerDraws) {
drawRepository.updateById(draw);
}
}

return winners;
}

/**
* 응모자 중 당첨자 생성
*
* @param entrants
* @param winnerCount
* @return
*/
private List<Entrant> pickRandomWinners(List<Entrant> entrants, int winnerCount) {
List<Entrant> winners = new ArrayList<>();
Random random = new Random();
Set<Integer> selectedIndices = new HashSet<>();

while (selectedIndices.size() < winnerCount) {
int index = random.nextInt(entrants.size());
if (!selectedIndices.contains(index)) {
selectedIndices.add(index);
winners.add(entrants.get(index));
}
}
return winners;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.gugbab2.productdraw.domain.vo;

public enum WinnerStatus {

PENDING, // 대기 중
WINNER, // 당첨
NOT_WINNER; // 미당첨
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.gugbab2.productdraw.dto;

import lombok.Getter;
import lombok.Setter;

public class DrawDto {

@Getter
@Setter
public static class CreateDrawDto{
private String entrantId;
private String productId;
}

}
Loading

0 comments on commit 1facfa4

Please sign in to comment.