Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/121 : 응모하기 API #169

Merged
merged 2 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.nexters.dailyphrase.common.annotation.Mapper;
import com.nexters.dailyphrase.common.enums.PrizeEntryStatus;
import com.nexters.dailyphrase.common.enums.PrizeTicketStatus;
import com.nexters.dailyphrase.prize.domain.Prize;
import com.nexters.dailyphrase.prize.domain.PrizeEntry;
import com.nexters.dailyphrase.prize.domain.PrizeEvent;
import com.nexters.dailyphrase.prize.domain.PrizeTicket;
Expand Down Expand Up @@ -60,4 +61,16 @@ public PrizeEventResponseDTO.PrizeEventInfo toPrizeEventInfo(PrizeEvent prizeEve
.status(prizeEvent.getStatus().getDescription())
.build();
}

public PrizeEntry toPrizeEntry(Long memberId, Prize prize) {
return PrizeEntry.builder().memberId(memberId).prize(prize).build();
}

public PrizeEventResponseDTO.EnterPrizeEvent toEnterPrizeEvent(final PrizeEntry prizeEntry) {
return PrizeEventResponseDTO.EnterPrizeEvent.builder()
.memberId(prizeEntry.getMemberId())
.prizeId(prizeEntry.getPrize().getId())
.status(prizeEntry.getStatus())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
import com.nexters.dailyphrase.common.jwt.JwtTokenService;
import com.nexters.dailyphrase.common.jwt.dto.AccessTokenInfo;
import com.nexters.dailyphrase.common.utils.MemberUtils;
import com.nexters.dailyphrase.prize.domain.Prize;
import com.nexters.dailyphrase.prize.domain.PrizeEntry;
import com.nexters.dailyphrase.prize.domain.PrizeEvent;
import com.nexters.dailyphrase.prize.domain.PrizeTicket;
import com.nexters.dailyphrase.prize.exception.InsufficientTicketsException;
import com.nexters.dailyphrase.prize.implement.*;
import com.nexters.dailyphrase.prize.presentation.dto.PrizeEventRequestDTO;
import com.nexters.dailyphrase.prize.presentation.dto.PrizeEventResponseDTO;
Expand All @@ -35,6 +37,7 @@ public class PrizeEventService {
private final PrizeTicketQueryAdapter prizeTicketQueryAdapter;
private final PrizeTicketCommandAdapter prizeTicketCommandAdapter;
private final PrizeEntryQueryAdapter prizeEntryQueryAdapter;
private final PrizeEntryCommandAdapter prizeEntryCommandAdapter;
private final JwtTokenService jwtTokenService;
private final PrizeEventMapper prizeEventMapper;
private final MemberUtils memberUtils;
Expand Down Expand Up @@ -101,4 +104,24 @@ public PrizeEventResponseDTO.EnterPhoneNumber enterPhoneNumber(
prizeEntry -> prizeEntry.setPhoneNumber(request.getPhoneNumber()));
return prizeEventMapper.toEnterPhoneNumber(memberId, prizeId, request.getPhoneNumber());
}

@Transactional
public PrizeEventResponseDTO.EnterPrizeEvent enterPrize(
final PrizeEventRequestDTO.EnterPrizeEvent request) {
Long memberId = memberUtils.getCurrentMemberId();
Prize prize = prizeQueryAdapter.findById(request.getPrizeId());
int requiredTicketCount = prize.getRequiredTicketCount();

List<PrizeTicket> prizeTicketList =
prizeTicketQueryAdapter.findPrizeTicketByMemberIdAndStatus(
memberId, PrizeTicketStatus.AVAILABLE, requiredTicketCount);
if (prizeTicketList.size() < requiredTicketCount)
throw InsufficientTicketsException.EXCEPTION;

prizeTicketList.forEach(prizeTicket -> prizeTicket.setStatus(PrizeTicketStatus.USED));
PrizeEntry savedPrizeEntry =
prizeEntryCommandAdapter.add(prizeEventMapper.toPrizeEntry(memberId, prize));

return prizeEventMapper.toEnterPrizeEvent(savedPrizeEntry);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ public class PrizeEntry extends BaseDateTimeEntity {
@JoinColumn(name = "prize_id", nullable = false)
private Prize prize;

@Builder.Default
@Enumerated(EnumType.STRING)
private PrizeEntryStatus status;
private PrizeEntryStatus status = PrizeEntryStatus.ENTERED;

public void setPhoneNumber(final String phoneNumber) {
this.phoneNumber = phoneNumber;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ public class PrizeTicket extends BaseDateTimeEntity {

@Enumerated(EnumType.STRING)
private PrizeTicketStatus status;

public void setStatus(PrizeTicketStatus status) {
this.status = status;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.nexters.dailyphrase.prize.domain.repository;

import java.util.List;

import com.nexters.dailyphrase.common.enums.PrizeTicketStatus;
import com.nexters.dailyphrase.prize.domain.PrizeTicket;

public interface PrizeTicketCustomRepository {
List<PrizeTicket> findByMemberIdAndStatus(Long memberId, PrizeTicketStatus status, int size);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.nexters.dailyphrase.prize.domain.repository;

import java.util.List;

import org.springframework.stereotype.Repository;

import com.nexters.dailyphrase.common.enums.PrizeTicketStatus;
import com.nexters.dailyphrase.prize.domain.PrizeTicket;
import com.nexters.dailyphrase.prize.domain.QPrizeTicket;
import com.querydsl.jpa.impl.JPAQueryFactory;

import lombok.RequiredArgsConstructor;

@Repository
@RequiredArgsConstructor
public class PrizeTicketCustomRepositoryImpl implements PrizeTicketCustomRepository {
private final JPAQueryFactory queryFactory;

@Override
public List<PrizeTicket> findByMemberIdAndStatus(
Long memberId, PrizeTicketStatus status, int size) {
QPrizeTicket qPrizeTicket = QPrizeTicket.prizeTicket;

return queryFactory
.selectFrom(qPrizeTicket)
.where(qPrizeTicket.memberId.eq(memberId).and(qPrizeTicket.status.eq(status)))
.limit(size)
.fetch();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@

import org.springframework.data.jpa.repository.JpaRepository;

import com.nexters.dailyphrase.common.enums.PrizeTicketStatus;
import com.nexters.dailyphrase.prize.domain.PrizeTicket;

public interface PrizeTicketRepository extends JpaRepository<PrizeTicket, Long> {
public interface PrizeTicketRepository
extends JpaRepository<PrizeTicket, Long>, PrizeTicketCustomRepository {
int countByMemberIdAndCreatedAtBetween(
Long memberId, LocalDateTime startDateTime, LocalDateTime endDateTime);

int countByMemberIdAndStatus(Long memberId, PrizeTicketStatus status);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.nexters.dailyphrase.prize.exception;

import com.nexters.dailyphrase.common.exception.BaseCodeException;

public class InsufficientTicketsException extends BaseCodeException {
public static BaseCodeException EXCEPTION = new InsufficientTicketsException();

private InsufficientTicketsException() {
super(PrizeEventErrorCode.INSUFFICIENT_TICKETS);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.nexters.dailyphrase.prize.exception;

import static com.nexters.dailyphrase.common.consts.DailyPhraseStatic.BAD_REQUEST;
import static com.nexters.dailyphrase.common.consts.DailyPhraseStatic.NOT_FOUND;

import java.lang.reflect.Field;
Expand All @@ -15,7 +16,9 @@
@Getter
@AllArgsConstructor
public enum PrizeEventErrorCode implements BaseErrorCode {
PRIZE_EVENT_NOT_FOUND(NOT_FOUND, "PHRASE_EVENT_404_1", "존재하지 않는 이벤트입니다.");
PRIZE_EVENT_NOT_FOUND(NOT_FOUND, "PRIZE_EVENT_404_1", "존재하지 않는 이벤트입니다."),
PRIZE_NOT_FOUND(NOT_FOUND, "PRIZE_404_1", "존재하지 않는 경품입니다."),
INSUFFICIENT_TICKETS(BAD_REQUEST, "PRIZE_TICKET_400_1", "티켓이 부족합니다.");

private final Integer status;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.nexters.dailyphrase.prize.exception;

import com.nexters.dailyphrase.common.exception.BaseCodeException;

public class PrizeNotFoundException extends BaseCodeException {
public static BaseCodeException EXCEPTION = new PrizeNotFoundException();

private PrizeNotFoundException() {
super(PrizeEventErrorCode.PRIZE_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.nexters.dailyphrase.prize.implement;

import com.nexters.dailyphrase.common.annotation.Adapter;
import com.nexters.dailyphrase.prize.domain.PrizeEntry;
import com.nexters.dailyphrase.prize.domain.repository.PrizeEntryRepository;

import lombok.RequiredArgsConstructor;

@Adapter
@RequiredArgsConstructor
public class PrizeEntryCommandAdapter {
private final PrizeEntryRepository prizeEntryRepository;

public PrizeEntry add(PrizeEntry prizeEntry) {
return prizeEntryRepository.save(prizeEntry);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.nexters.dailyphrase.prize.implement;

import com.nexters.dailyphrase.common.annotation.Adapter;
import com.nexters.dailyphrase.prize.domain.Prize;
import com.nexters.dailyphrase.prize.domain.repository.PrizeRepository;
import com.nexters.dailyphrase.prize.exception.PrizeNotFoundException;
import com.nexters.dailyphrase.prize.presentation.dto.PrizeEventResponseDTO;

import lombok.RequiredArgsConstructor;
Expand All @@ -14,4 +16,10 @@ public class PrizeQueryAdapter {
public PrizeEventResponseDTO.PrizeList findPrizeListDTO(final Long eventId) {
return prizeRepository.findPrizeListDTO(eventId);
}

public Prize findById(Long prizeId) {
return prizeRepository
.findById(prizeId)
.orElseThrow(() -> PrizeNotFoundException.EXCEPTION);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

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

import com.nexters.dailyphrase.common.annotation.Adapter;
import com.nexters.dailyphrase.common.enums.PrizeTicketStatus;
import com.nexters.dailyphrase.prize.domain.PrizeTicket;
import com.nexters.dailyphrase.prize.domain.repository.PrizeTicketRepository;

import lombok.RequiredArgsConstructor;
Expand All @@ -21,4 +24,9 @@ public Integer countPrizeTicketByMemberIdAndLocalDate(
return prizeTicketRepository.countByMemberIdAndCreatedAtBetween(
memberId, startOfDay, endOfDay);
}

public List<PrizeTicket> findPrizeTicketByMemberIdAndStatus(
final Long memberId, final PrizeTicketStatus status, final int count) {
return prizeTicketRepository.findByMemberIdAndStatus(memberId, status, count);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,16 @@ public CommonResponse<PrizeEventResponseDTO.PrizeList> getPrizeList() {
}

@Operation(
summary = "07-03 Event 🎁 경품 응모 이벤트의 경품 응모 결과 확인 Made By 성훈",
summary = "07-03 Event 🎁 경품 응모 이벤트의 경품 응모 Made By 성훈",
description = "경품 응모 이벤트의 경품 응모 API입니다.")
@PostMapping("/enter")
public CommonResponse<PrizeEventResponseDTO.EnterPrizeEvent> enterPrize(
@RequestBody PrizeEventRequestDTO.EnterPrizeEvent request) {
return CommonResponse.onSuccess(prizeEventService.enterPrize(request));
}

@Operation(
summary = "07-04 Event 🎁 경품 응모 이벤트의 경품 응모 결과 확인 Made By 성훈",
description = "경품 응모 이벤트의 경품 응모 결과 확인 API입니다.")
@GetMapping("/prizes/{prizeId}/entry-result")
public CommonResponse<PrizeEventResponseDTO.PrizeEntryResult> getPrizeEntryResult(
Expand All @@ -55,7 +64,7 @@ public CommonResponse<PrizeEventResponseDTO.PrizeEntryResult> getPrizeEntryResul
}

@Operation(
summary = "07-04 Event 🎁 경품 응모 이벤트의 당첨자 연락처 입력 Made By 성훈",
summary = "07-05 Event 🎁 경품 응모 이벤트의 당첨자 연락처 입력 Made By 성훈",
description = "경품 응모 이벤트의 당첨자 연락처 입력 API입니다.")
@PostMapping("/prizes/{prizeId}/phone-number")
public CommonResponse<PrizeEventResponseDTO.EnterPhoneNumber> enterPhoneNumber(
Expand All @@ -65,7 +74,7 @@ public CommonResponse<PrizeEventResponseDTO.EnterPhoneNumber> enterPhoneNumber(
}

@Operation(
summary = "07-05 Event 🎁 경품 응모 이벤트의 응모권 발급용 카카오 콜백 Made By 성훈",
summary = "07-06 Event 🎁 경품 응모 이벤트의 응모권 발급용 카카오 콜백 Made By 성훈",
description = "경품 응모 이벤트의 응모권 발급용 카카오 콜백입니다. (직접 호출 X)")
@PostMapping("/kakaolink/callback")
public ResponseEntity<String> handleKakaoLinkCallback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ public class PrizeEventRequestDTO {
public static class EnterPhoneNumber {
private String phoneNumber;
}

@Getter
public static class EnterPrizeEvent {
private Long prizeId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,14 @@ public static class PrizeEventInfo {
private LocalDateTime eventWinnerAnnouncementDateTime;
private String status;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class EnterPrizeEvent {
private Long prizeId;
private Long memberId;
private PrizeEntryStatus status;
}
}
Loading
Loading