Skip to content

Commit

Permalink
행사 도메인 리팩토링 (#325)
Browse files Browse the repository at this point in the history
  • Loading branch information
juno-junho authored Apr 28, 2024
1 parent 4877871 commit cb58c1a
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import java.time.LocalDateTime;

@Controller
@RequestMapping("/api/v1/events")
@RequiredArgsConstructor
Expand All @@ -25,11 +27,13 @@ public class ParticipationController {

@PostMapping("/participate")
public ResponseEntity<Void> apply(@RequestBody EventParticipationCreateRequest request, @Authenticated JwtUser jwtUser) {
LocalDateTime now = LocalDateTime.now();
EventParticipationCreateInfo eventParticipationCreateInfo = EventParticipationCreateInfo.builder()
.userId(jwtUser.id())
.eventId(request.eventId())
.formAnswers(request.toEntityList())
.ticketCount(request.ticketCount())
.now(now)
.build();

participationService.apply(eventParticipationCreateInfo);
Expand Down
61 changes: 34 additions & 27 deletions src/main/java/com/spaceclub/event/domain/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ public Event registerForm(Form form) {

public Event registerPosterImage(String posterImageName) {
return event()
.eventInfo(this.eventInfo.registerPosterImage(posterImageName))
.eventInfo(eventInfo.registerPosterImage(posterImageName))
.build();
}

public Event registerParticipants(int participants) {
return event()
.eventInfo(this.eventInfo.registerParticipants(participants))
.eventInfo(eventInfo.registerParticipants(participants))
.build();
}

Expand Down Expand Up @@ -158,11 +158,26 @@ private EventBuilder event() {
}

public Boolean isAbleToApply(LocalDateTime now) {
if (this.formInfo.getFormOpenDateTime() == null) return null;
if (this.formInfo.getFormCloseDateTime() == null) return null;
if (getFormOpenDateTime() == null) return null;
if (getFormCloseDateTime() == null) return null;

return this.formInfo.getFormOpenDateTime().isBefore(now)
&& this.formInfo.getFormCloseDateTime().isAfter(now);
return getFormOpenDateTime().isBefore(now)
&& getFormCloseDateTime().isAfter(now);
}

public LocalDateTime getFormOpenDateTime() {
return formInfo.getFormOpenDateTime();
}

public LocalDateTime getFormCloseDateTime() {
return formInfo.getFormCloseDateTime();
}

public ParticipationStatus getApplyStatus() {
if (isFormManaged()) {
return ParticipationStatus.PENDING;
}
return ParticipationStatus.CONFIRMED;
}

public boolean hasForm() {
Expand Down Expand Up @@ -232,14 +247,6 @@ public String getClubCoverImageName() {
return club.getCoverImageName();
}

public LocalDateTime getFormOpenDateTime() {
return formInfo.getFormOpenDateTime();
}

public LocalDateTime getFormCloseDateTime() {
return formInfo.getFormCloseDateTime();
}

public LocalDate getFormOpenDate() {
return formInfo.getFormOpenDateTime().toLocalDate();
}
Expand All @@ -266,7 +273,7 @@ public String getContent() {
return this.eventInfo.getContent();
}

public boolean isFormed() {
public boolean isFormExists() {
return form != null;
}

Expand All @@ -275,49 +282,49 @@ public boolean isFormManaged() {
}

public boolean isNotFormManaged() {
return !this.isFormManaged();
return !isFormManaged();
}

public Integer getMaxTicketCount() {
return ticketInfo.getMaxTicketCount();
}

public Integer getDues() {
return this.eventInfo.getDues();
return eventInfo.getDues();
}

public Integer getCapacity() {
return this.eventInfo.getCapacity();
return eventInfo.getCapacity();
}

public String getRecruitmentTarget() {
return this.eventInfo.getRecruitmentTarget();
return eventInfo.getRecruitmentTarget();
}

public String getActivityArea() {
return this.eventInfo.getActivityArea();
return eventInfo.getActivityArea();
}

public Integer getCost() {
return this.ticketInfo.getCost();
return ticketInfo.getCost();
}

public String getBankName() {
if (this.bankInfo == null) return null;
return this.bankInfo.getBankName();
if (bankInfo == null) return null;
return bankInfo.getBankName();
}

public Integer getRecruitmentLimit() {
return this.eventInfo.getRecruitmentLimit();
return eventInfo.getRecruitmentLimit();
}

public String getBankAccountNumber() {
if (this.bankInfo == null) return null;
return this.bankInfo.getBankAccountNumber();
if (bankInfo == null) return null;
return bankInfo.getBankAccountNumber();
}

public int getParticipants() {
return this.eventInfo.getParticipants();
return eventInfo.getParticipants();
}

}
4 changes: 4 additions & 0 deletions src/main/java/com/spaceclub/event/domain/EventUser.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,8 @@ public EventCategory getEventCategory() {
return event.getCategory();
}

public boolean isCanceled() {
return CANCELED == status;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static com.spaceclub.event.EventExceptionMessage.EVENT_NOT_FOUND;
import static com.spaceclub.event.EventExceptionMessage.EXCEED_TICKET_COUNT;
import static com.spaceclub.event.EventExceptionMessage.TICKET_COUNT_REQUIRED;
import static com.spaceclub.event.domain.EventCategory.SHOW;

@Component
@RequiredArgsConstructor
Expand All @@ -19,7 +20,13 @@ public Event validateEventWithLock(Long eventId) {
return eventRepository.findWithLockById(eventId).orElseThrow(() -> new IllegalStateException(EVENT_NOT_FOUND.toString()));
}

public void validateMaxEventTicketCount(Integer maxTicketCount, Integer ticketCount) {
public void validateTicketCount(Integer ticketCount, Event event) {
if (SHOW == event.getCategory()) {
validateMaxEventTicketCount(event.getMaxTicketCount(), ticketCount);
}
}

private void validateMaxEventTicketCount(Integer maxTicketCount, Integer ticketCount) {
if (ticketCount == null) {
throw new IllegalArgumentException(TICKET_COUNT_REQUIRED.toString());
}
Expand Down
107 changes: 50 additions & 57 deletions src/main/java/com/spaceclub/event/service/ParticipationService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.spaceclub.event.domain.ParticipationStatus;
import com.spaceclub.event.domain.repository.EventUserRepository;
import com.spaceclub.event.service.vo.EventParticipationCreateInfo;
import com.spaceclub.form.domain.FormAnswer;
import com.spaceclub.form.service.FormOptionProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -18,13 +17,9 @@
import static com.spaceclub.event.EventExceptionMessage.EVENT_NOT_APPLIED;
import static com.spaceclub.event.EventExceptionMessage.EXCEED_CAPACITY;
import static com.spaceclub.event.EventExceptionMessage.NOT_APPLICABLE_DATE;
import static com.spaceclub.event.domain.EventCategory.SHOW;
import static com.spaceclub.event.domain.ParticipationStatus.CANCELED;
import static com.spaceclub.event.domain.ParticipationStatus.CONFIRMED;
import static com.spaceclub.event.domain.ParticipationStatus.PENDING;

@Service
@Transactional
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ParticipationService {

Expand All @@ -36,100 +31,98 @@ public class ParticipationService {

private final EventValidator eventValidator;

@Transactional
public void apply(EventParticipationCreateInfo info) {
Event event = eventValidator.validateEventWithLock(info.eventId());

validateTicketCount(info.ticketCount(), event);
eventValidator.validateTicketCount(info.ticketCount(), event);

Optional<EventUser> optionalEventUser = eventUserRepository.findByEventIdAndUserId(info.eventId(), info.userId());
optionalEventUser.ifPresent(eventUser -> processExistingUser(event.isFormExists(), info, eventUser));

optionalEventUser.ifPresentOrElse(eventUser -> {
processByParticipationStatus(event.isFormed(), info, eventUser);
participateEvent(info, event);
},
() -> participateEvent(info, event));
participateEvent(info, event);
}

private void validateTicketCount(Integer ticketCount, Event event) {
if (SHOW.equals(event.getCategory())) {
eventValidator.validateMaxEventTicketCount(event.getMaxTicketCount(), ticketCount);
private void processExistingUser(boolean isFormExists, EventParticipationCreateInfo info, EventUser eventUser) {
if (eventUser.isCanceled()) { // eventUser 상태가 취소 상태이면 삭제
deleteUserParticipation(isFormExists, info, eventUser);
} else { // 취소상태가 아니면 이미 신청
throw new IllegalArgumentException(EVENT_ALREADY_APPLIED.toString());
}
}

private void processByParticipationStatus(boolean isFormed, EventParticipationCreateInfo info, EventUser eventUser) {
if (CANCELED.equals(eventUser.getStatus())) {
eventUserRepository.deleteById(eventUser.getId());
private void deleteUserParticipation(boolean isFormExists, EventParticipationCreateInfo info, EventUser eventUser) {
eventUserRepository.deleteById(eventUser.getId());
deleteFormAnswerIfFormExists(isFormExists, info);
}

if (isFormed) {
formOptionProvider.deleteFormAnswer(info.formAnswers(), info.userId());
}
} else {
throw new IllegalArgumentException(EVENT_ALREADY_APPLIED.toString());
private void deleteFormAnswerIfFormExists(boolean isFormExists, EventParticipationCreateInfo info) {
if (isFormExists) { // form이 존재하면 formAnswer 삭제
formOptionProvider.deleteFormAnswer(info.formAnswers(), info.userId());
}
}

private void participateEvent(EventParticipationCreateInfo info, Event event) {
for (FormAnswer formAnswer : info.formAnswers()) {
formOptionProvider.createFormOption(info.userId(), formAnswer);
}

int participants = addParticipants(info, event);
saveFormInformation(info); // 참여 시 폼 정보 저장
int updatedParticipantCount = addAndValidateParticipantCount(info, event);

Event updateEvent = event.registerParticipants(participants);
Event updateEvent = event.registerParticipants(updatedParticipantCount);
eventProvider.update(updateEvent);

if (event.isFormManaged()) createNewUser(info.userId(), event, PENDING, info.ticketCount());
else createNewUser(info.userId(), event, CONFIRMED, info.ticketCount());
createParticipant(info, event);
}

public void createNewUser(Long userId, Event event, ParticipationStatus status, int ticketCount) {
EventUser newEventUser = EventUser.builder()
.userId(userId)
.event(event)
.status(status)
.ticketCount(ticketCount)
.build();

eventUserRepository.save(newEventUser);
private void saveFormInformation(EventParticipationCreateInfo info) {
info.formAnswers()
.forEach(formAnswer -> formOptionProvider.createFormOption(info.userId(), formAnswer));
}

private int addParticipants(EventParticipationCreateInfo info, Event event) {
int participants = event.getParticipants() + info.ticketCount();
validateCapacity(event.getCapacity(), participants);
validateFormDate(event.getFormOpenDateTime(), event.getFormCloseDateTime());
private int addAndValidateParticipantCount(EventParticipationCreateInfo info, Event event) {
int totalParticipants = event.getParticipants() + info.ticketCount();// event의 현재 참여자수 + 신청한 티켓 수
validateIfCapacityIsNotExceeded(event.getCapacity(), totalParticipants);
validateIfRegistrationTime(event, info.now());

return participants;
return totalParticipants;
}

private void validateCapacity(Integer capacity, int participants) {
private void validateIfCapacityIsNotExceeded(Integer capacity, int participants) {
if (participants > capacity) {
throw new IllegalStateException(EXCEED_CAPACITY.toString());
}
}

private void validateFormDate(LocalDateTime formOpen, LocalDateTime formClose) {
LocalDateTime now = LocalDateTime.now();
boolean invalidParticipationDate = now.isAfter(formClose) || now.isBefore(formOpen);

if (invalidParticipationDate) {
private void validateIfRegistrationTime(Event event, LocalDateTime now) {
Boolean isWithinAllowedTimeFrame = event.isAbleToApply(now);
if (isWithinAllowedTimeFrame == null || !isWithinAllowedTimeFrame) {
throw new IllegalStateException(NOT_APPLICABLE_DATE.toString());
}
}

private void createParticipant(EventParticipationCreateInfo participationInfo, Event event) {
ParticipationStatus status = event.getApplyStatus(); // 폼이 관리 상태이면 PENDING | 관리 상태가 아니면 CONFIRMED
EventUser newEventUser = EventUser.builder()
.userId(participationInfo.userId())
.event(event)
.status(status)
.ticketCount(participationInfo.ticketCount())
.build();

eventUserRepository.save(newEventUser);
}

@Transactional
public ParticipationStatus cancel(Long eventId, Long userId) {
Event event = eventValidator.validateEventWithLock(eventId);

EventUser eventUser = eventUserRepository.findByEventIdAndUserId(eventId, userId)
EventUser eventUser = eventUserRepository.findByEventIdAndUserId(eventId, userId) // EventUser 검증
.orElseThrow(() -> new IllegalArgumentException(EVENT_NOT_APPLIED.toString()));

if (event.isNotFormManaged()) {
if (event.isNotFormManaged()) { // 관리 모드가 아닐 경우 참여자 수 감소
eventProvider.minusParticipants(event, eventUser.getTicketCount());
}
EventUser updateEventUser = eventUser.cancelEvent(event.isFormManaged());

EventUser updateEventUser = eventUser.cancelEvent(event.isFormManaged()); // 관리 모드일 경우 cancel request로 변경 / 아닐 경우 canceled로 변경
eventUserRepository.save(updateEventUser);

return updateEventUser.getStatus();
return updateEventUser.getStatus(); // 현재 상태 반환 (cancel request or canceled)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import com.spaceclub.form.domain.FormAnswer;
import lombok.Builder;

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

public record EventParticipationCreateInfo(
Long userId,
Long eventId,
List<FormAnswer> formAnswers,
Integer ticketCount
Integer ticketCount,
LocalDateTime now
) {

@Builder
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/spaceclub/form/service/FormService.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class FormService {
public Long create(FormCreateInfo formInfo) {
Event event = eventProvider.getById(formInfo.eventId());
clubUserValidator.validateClubManager(event.getClubId(), formInfo.userId());
if (event.isFormed()) throw new IllegalStateException(EXISTED_FORM.toString());
if (event.isFormExists()) throw new IllegalStateException(EXISTED_FORM.toString());

formInfo.form().addItems(formInfo.options());
Form savedForm = formRepository.save(formInfo.form());
Expand Down
Loading

0 comments on commit cb58c1a

Please sign in to comment.