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

feat : 티켓 상품 생성 #164

Merged
merged 7 commits into from
Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
@@ -0,0 +1,31 @@
package band.gosrock.api.ticketItem.controller;


import band.gosrock.api.ticketItem.dto.request.CreateTicketItemRequest;
import band.gosrock.api.ticketItem.dto.response.CreateTicketItemResponse;
import band.gosrock.api.ticketItem.service.CreateTicketItemUseCase;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@SecurityRequirement(name = "access-token")
@Tag(name = "티켓 상품 관련 컨트롤러")
@RestController
@RequestMapping("/v1/ticket_items")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ticketItems 로 해유!
저희 이렇게 컨벤션 자연스래? 맞춰진것같아요

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

뉑뉑

@RequiredArgsConstructor
public class TicketItemController {

public final CreateTicketItemUseCase createTicketItemUseCase;

@Operation(
summary = "특정 이벤트에 속하는 티켓 상품을 생성합니다.",
description = "제휴 되지 않은 회원은 티켓 가격 0으로 강제해 보내주세요!")
@PostMapping
public CreateTicketItemResponse createTicketItem(
@RequestBody @Valid CreateTicketItemRequest createTicketItemRequest) {
return createTicketItemUseCase.execute(createTicketItemRequest);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package band.gosrock.api.ticketItem.dto.request;


import band.gosrock.domain.common.vo.Money;
import band.gosrock.domain.domains.event.domain.Event;
import band.gosrock.domain.domains.ticket_item.domain.TicketItem;
import band.gosrock.domain.domains.ticket_item.domain.TicketType;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.lang.Nullable;

@Getter
@RequiredArgsConstructor
public class CreateTicketItemRequest {

@NotNull
@Schema(nullable = false, example = "1")
private Long eventId;

@NotNull
@Schema(nullable = false, defaultValue = "FIRST_COME_FIRST_SERVED")
private TicketType type;

@NotNull
@Schema(nullable = false, example = "일반 티켓")
private String name;

@Nullable
@Schema(nullable = true, example = "일반 입장 티켓입니다.")
private String description;

@NotNull
@Schema(nullable = false, example = "4000")
private Long price;

@NotNull
@Schema(nullable = false, example = "100")
private Long supplyCount;

@NotNull
@Schema(nullable = false, example = "1")
private Long purchaseLimit;

public TicketItem toEntity(Event event) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 처음에 request dto에 넣었었는데 mapper 만들어서 거기서 빌더쓰는 게 좀 더 깔끔해 보이는 것 같아요.
리팩토링하면 mapper로 옮기려구요.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오케이 저두 리펙해보겠슴다


return TicketItem.builder()
.type(type)
.name(name)
.description(description)
.price(Money.wons(price))
.quantity(supplyCount)
.supplyCount(supplyCount)
.purchaseLimit(purchaseLimit)
.isSellable(true)
.event(event)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package band.gosrock.api.ticketItem.dto.response;


import band.gosrock.domain.common.vo.Money;
import band.gosrock.domain.domains.ticket_item.domain.TicketItem;
import band.gosrock.domain.domains.ticket_item.domain.TicketType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class CreateTicketItemResponse {
@Schema(description = "티켓상품 id")
private final Long ticketItemId;

@Schema(description = "이름")
private final String ticketName;

@Schema(description = "설명")
private final String description;

@Schema(description = "가격")
private final Money price;

@Schema(description = "티켓 타입")
private final TicketType type;

@Schema(description = "1인당 구매 제한 매수")
private final Long purchaseLimit;

@Schema(description = "공급량")
private final Long supplyCount;

@Schema(description = "재고")
private final Long quantity;

public static CreateTicketItemResponse from(TicketItem ticketItem) {

return CreateTicketItemResponse.builder()
.ticketItemId(ticketItem.getId())
.ticketName(ticketItem.getName())
.description(ticketItem.getDescription())
.price(ticketItem.getPrice())
.type(ticketItem.getType())
.purchaseLimit(ticketItem.getPurchaseLimit())
.supplyCount(ticketItem.getSupplyCount())
.quantity(ticketItem.getQuantity())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package band.gosrock.api.ticketItem.service;


import band.gosrock.api.common.UserUtils;
import band.gosrock.api.ticketItem.dto.request.CreateTicketItemRequest;
import band.gosrock.api.ticketItem.dto.response.CreateTicketItemResponse;
import band.gosrock.common.annotation.UseCase;
import band.gosrock.domain.common.vo.Money;
import band.gosrock.domain.domains.event.adaptor.EventAdaptor;
import band.gosrock.domain.domains.event.domain.Event;
import band.gosrock.domain.domains.host.adaptor.HostAdaptor;
import band.gosrock.domain.domains.host.domain.Host;
import band.gosrock.domain.domains.host.service.HostService;
import band.gosrock.domain.domains.ticket_item.domain.TicketItem;
import band.gosrock.domain.domains.ticket_item.service.TicketItemService;
import band.gosrock.domain.domains.user.domain.User;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

@UseCase
@RequiredArgsConstructor
public class CreateTicketItemUseCase {

private final EventAdaptor eventAdaptor;
private final HostAdaptor hostAdaptor;
private final UserUtils userUtils;
private final HostService hostService;
private final TicketItemService ticketItemService;

@Transactional
public CreateTicketItemResponse execute(CreateTicketItemRequest createTicketItemRequest) {
User user = userUtils.getCurrentUser();
Event event = eventAdaptor.findById(createTicketItemRequest.getEventId());
Host host = hostAdaptor.findById(event.getHostId());
// 권한 체크 ( 해당 이벤트의 호스트인지 )
hostService.hasHostUser(host, user.getId());
// 호스트 제휴 여부에 따른 가격 체크
if (!host.getPartner()) {
ticketItemService.checkTicketPrice(Money.wons(createTicketItemRequest.getPrice()));
}
TicketItem ticketItem =
ticketItemService.createTicketItem(createTicketItemRequest.toEntity(event));
return CreateTicketItemResponse.from(ticketItem);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

약간 이부분이 맘에 안들긴하는데..
흐음 저도 잘모르겠네요

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ public TicketItem queryTicketItem(Long ticketItemId) {
.findById(ticketItemId)
.orElseThrow(() -> TicketItemNotFoundException.EXCEPTION);
}

public TicketItem save(TicketItem ticketItem) {
return ticketItemRepository.save(ticketItem);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public TicketItem(
Boolean isSellable,
LocalDateTime saleStartAt,
LocalDateTime saleEndAt,
Event event,
List<ItemOptionGroup> itemOptionGroups) {
this.type = type;
this.name = name;
Expand All @@ -85,6 +86,7 @@ public TicketItem(
this.isSellable = isSellable;
this.saleStartAt = saleStartAt;
this.saleEndAt = saleEndAt;
this.event = event;
this.itemOptionGroups = itemOptionGroups;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package band.gosrock.domain.domains.ticket_item.exception;


import band.gosrock.common.exception.DuDoongCodeException;

public class InvalidTicketPriceException extends DuDoongCodeException {

public static final DuDoongCodeException EXCEPTION = new InvalidTicketPriceException();

private InvalidTicketPriceException() {
super(TicketItemErrorCode.INVALID_TICKET_PRICE);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package band.gosrock.domain.domains.ticket_item.exception;

import static band.gosrock.common.consts.DuDoongStatic.BAD_REQUEST;
import static band.gosrock.common.consts.DuDoongStatic.NOT_FOUND;

import band.gosrock.common.annotation.ExplainError;
Expand All @@ -16,7 +17,9 @@ public enum TicketItemErrorCode implements BaseErrorCode {
@ExplainError("요청에서 보내준 티켓 상품 id 값이 올바르지 않을 때 발생하는 오류입니다.")
TICKET_ITEM_NOT_FOUND(NOT_FOUND, "Ticket_Item_404_1", "티켓 아이템을 찾을 수 없습니다."),
@ExplainError("요청에서 보내준 옵션 id 값이 올바르지 않을 때 발생하는 오류입니다.")
OPTION_NOT_FOUND(NOT_FOUND, "Option_404_1", "옵션을 찾을 수 없습니다.");
OPTION_NOT_FOUND(NOT_FOUND, "Option_404_1", "옵션을 찾을 수 없습니다."),
@ExplainError("제휴되지 않은 호스트가 티켓 가격을 0이 아닌 값으로 요청했을때 발생하는 오류입니다.")
INVALID_TICKET_PRICE(BAD_REQUEST, "Ticket_Item_400_1", "티켓 가격을 설정할 수 없습니다.");

private Integer status;
private String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package band.gosrock.domain.domains.ticket_item.service;


import band.gosrock.common.annotation.DomainService;
import band.gosrock.domain.common.vo.Money;
import band.gosrock.domain.domains.ticket_item.adaptor.TicketItemAdaptor;
import band.gosrock.domain.domains.ticket_item.domain.TicketItem;
import band.gosrock.domain.domains.ticket_item.exception.InvalidTicketPriceException;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

@DomainService
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class TicketItemService {

private final TicketItemAdaptor ticketItemAdaptor;

@Transactional
public TicketItem createTicketItem(TicketItem ticketItem) {
return ticketItemAdaptor.save(ticketItem);
}

@Transactional
public void checkTicketPrice(Money ticketPrice) {
if (!Money.ZERO.equals(ticketPrice)) {
throw InvalidTicketPriceException.EXCEPTION;
}
}
}