Skip to content

Commit

Permalink
Api-v1.0.2-4
Browse files Browse the repository at this point in the history
Api-v1.0.2-4
  • Loading branch information
ImNM authored Mar 8, 2023
2 parents 84cb26a + ebff708 commit 40ee07e
Show file tree
Hide file tree
Showing 23 changed files with 248 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@


import band.gosrock.api.alimTalk.dto.OrderAlimTalkDto;
import band.gosrock.api.alimTalk.service.helper.NcpHelper;
import band.gosrock.domain.common.alarm.OrderKakaoTalkAlarm;
import band.gosrock.infrastructure.config.alilmTalk.NcpHelper;
import band.gosrock.infrastructure.config.alilmTalk.dto.AlimTalkEventInfo;
import band.gosrock.infrastructure.config.alilmTalk.dto.AlimTalkOrderInfo;
import band.gosrock.infrastructure.config.alilmTalk.dto.AlimTalkUserInfo;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package band.gosrock.api.alimTalk.service;


import band.gosrock.api.alimTalk.service.helper.NcpHelper;
import band.gosrock.domain.common.alarm.UserKakaoTalkAlarm;
import band.gosrock.infrastructure.config.alilmTalk.NcpHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@


import band.gosrock.api.alimTalk.dto.OrderAlimTalkDto;
import band.gosrock.api.alimTalk.service.helper.NcpHelper;
import band.gosrock.domain.common.alarm.OrderKakaoTalkAlarm;
import band.gosrock.infrastructure.config.alilmTalk.NcpHelper;
import band.gosrock.infrastructure.config.alilmTalk.dto.AlimTalkEventInfo;
import band.gosrock.infrastructure.config.alilmTalk.dto.AlimTalkOrderInfo;
import band.gosrock.infrastructure.config.alilmTalk.dto.AlimTalkUserInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.bucket4j.Bucket;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
Expand All @@ -26,17 +28,28 @@ public class ThrottlingInterceptor implements HandlerInterceptor {
private final IPRateLimiter ipRateLimiter;
private final ObjectMapper objectMapper;

@Value("${acl.whiteList}")
private List<String> aclWhiteList;

private final SlackThrottleErrorSender slackThrottleErrorSender;

@Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws IOException {
Long userId = SecurityUtils.getCurrentUserId();
String remoteAddr = request.getRemoteAddr();
log.info("remoteAddr : " + remoteAddr);

// next js ssr 대응
if (aclWhiteList.contains(remoteAddr)) {
log.info("white List pass" + remoteAddr);
return true;
}

Bucket bucket;
if (userId == 0L) {
// 익명 유저 ip 기반처리
String remoteAddr = request.getRemoteAddr();
bucket = ipRateLimiter.resolveBucket(remoteAddr);
} else {
// 비 익명 유저 유저 아이디 기반 처리
Expand Down
2 changes: 2 additions & 0 deletions DuDoong-Api/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ swagger:
throttle:
overdraft: ${RATE_LIMIT_OVERDRAFT:60}
greedyRefill: ${RATE_LIMIT_REFILL:60}

acl.whiteList : ${ACL_WHITELIST:127.0.0.1,127.0.0.2}
---
spring:
config:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package band.gosrock.job;


import band.gosrock.domain.common.alarm.SettlementKakaoTalkAlarm;
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.user.adaptor.UserAdaptor;
import band.gosrock.domain.domains.user.domain.User;
import band.gosrock.infrastructure.config.alilmTalk.NcpHelper;
import band.gosrock.parameter.EventJobParameter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Slf4j
@RequiredArgsConstructor
@Configuration
public class EventSettlementAlimTalkToHost {

private static final String JOB_NAME = "이벤트정산_알림톡발송_호스트";
private static final String BEAN_PREFIX = JOB_NAME + "_";

private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final EventAdaptor eventAdaptor;
private final HostAdaptor hostAdaptor;
private final UserAdaptor userAdaptor;
private final NcpHelper ncpHelper;

@Bean(BEAN_PREFIX + "eventJobParameter")
@JobScope
public EventJobParameter eventJobParameter() {
return new EventJobParameter(eventAdaptor);
}

@Qualifier(BEAN_PREFIX + "eventJobParameter")
private final EventJobParameter eventJobParameter;

@Bean(JOB_NAME)
public Job slackUserStatisticJob() {
return jobBuilderFactory.get(JOB_NAME).preventRestart().start(eventSettlement()).build();
}

@Bean(BEAN_PREFIX + "step")
@JobScope
public Step eventSettlement() {
return stepBuilderFactory
.get(BEAN_PREFIX + "step")
.tasklet(
(contribution, chunkContext) -> {
log.info(">>>>> 정산서 전송 안내 알림톡 스탭");
Event event = eventJobParameter.getEvent();
Host host = hostAdaptor.findById(event.getHostId());
User masterUser = userAdaptor.queryUser(host.getMasterUserId());

String to =
masterUser
.getProfile()
.getPhoneNumberVo()
.getNaverSmsToNumber();
String content =
SettlementKakaoTalkAlarm.creationOf(
masterUser.getProfile().getName());

ncpHelper.sendSettlementNcpAlimTalk(
to,
SettlementKakaoTalkAlarm.creationTemplateCode(),
content,
SettlementKakaoTalkAlarm.creationHeaderOf(),
masterUser.getProfile().getEmail(),
event.getEventBasic().getName());
return RepeatStatus.FINISHED;
})
.build();
}
}
1 change: 0 additions & 1 deletion DuDoong-Batch/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ spring:
- common
batch.job.names: ${job.name:NONE}


---
spring:
config:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package band.gosrock.domain.common.alarm;


import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class SettlementKakaoTalkAlarm {

public static String creationOf(String hostName) {
return "안녕하세요 " + hostName + "님!\n" + "이메일로 정산서 발송이 완료되어 안내드립니다.";
}

public static String creationHeaderOf() {
return "정산서 이메일 발송 안내";
}

public static String creationTemplateCode() {
return "settlement";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ public Object lock(final ProceedingJoinPoint joinPoint) throws Throwable {
try {
rLock.unlock();
} catch (IllegalMonitorStateException e) {
rLock.forceUnlock();
log.error(e + baseKey + dynamicKey);
throw e;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void validItemStockEnough(Cart cart, TicketItem item) {

/** 이벤트가 현재 열려있는 상태인지 확인합니다. */
public void validEventIsOpen(Event event) {
event.validateStatusOpen();
event.validateNotOpenStatus();
}

/** 카트에 담길때 아이템이 한 종류인지 확인합니다. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public Slice<Event> querySliceEventsByKeyword(String keyword, Pageable pageable)
return eventRepository.querySliceEventsByKeyword(keyword, pageable);
}

public List<Event> queryEventsByEndAtBefore(LocalDateTime time) {
return eventRepository.queryEventsByEndAtBefore(time);
public List<Event> queryEventsByEndAtBeforeAndStatusOpen(LocalDateTime time) {
return eventRepository.queryEventsByEndAtBeforeAndStatusOpen(time);
}

public List<Event> findAllByIds(List<Long> ids) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,16 @@ public Event(Long hostId, String name, LocalDateTime startAt, Long runTime) {
Events.raise(EventCreationEvent.of(hostId, name));
}

public void validateStartAt() {
if (this.getStartAt().isBefore(LocalDateTime.now()))
throw EventOpenTimeExpiredException.EXCEPTION;
}

public void validateOpenStatus() {
if (status == OPEN) throw CannotModifyOpenEventException.EXCEPTION;
// todo : 오픈 전과 후 검증 로직 이름 변경
}

public void validateStatusOpen() {
public void validateNotOpenStatus() {
if (status != OPEN) throw EventNotOpenException.EXCEPTION;
}

Expand Down Expand Up @@ -145,6 +149,7 @@ public void prepare() {
}

public void open() {
validateStartAt();
updateStatus(OPEN, AlreadyOpenStatusException.EXCEPTION);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public enum EventErrorCode implements BaseErrorCode {
ALREADY_DELETED_STATUS(BAD_REQUEST, "Event_400_12", "이미 삭제된 이벤트입니다."),
CANNOT_DELETE_BY_ISSUED_TICKET(BAD_REQUEST, "Event_400_13", "발급 티켓이 있는 이벤트는 삭제할 수 없습니다."),
CANNOT_DELETE_BY_OPEN_EVENT(BAD_REQUEST, "Event_400_14", "오픈 상태인 이벤트는 삭제할 수 없습니다."),
OPEN_TIME_EXPIRED(BAD_REQUEST, "Event_400_15", "오픈 예정 시간이 현재 시간보다 빠릅니다."),

USE_OTHER_API(BAD_REQUEST, "Event_400_8", "잘못된 접근입니다.");

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


import band.gosrock.common.exception.DuDoongCodeException;

public class EventOpenTimeExpiredException extends DuDoongCodeException {

public static final DuDoongCodeException EXCEPTION = new EventOpenTimeExpiredException();

private EventOpenTimeExpiredException() {
super(EventErrorCode.OPEN_TIME_EXPIRED);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ public interface EventCustomRepository {

Slice<Event> querySliceEventsByKeyword(String keyword, Pageable pageable);

List<Event> queryEventsByEndAtBefore(LocalDateTime time);
List<Event> queryEventsByEndAtBeforeAndStatusOpen(LocalDateTime time);
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ public Slice<Event> querySliceEventsByKeyword(String keyword, Pageable pageable)
}

@Override
public List<Event> queryEventsByEndAtBefore(LocalDateTime time) {
return queryFactory.selectFrom(event).where(endAtBefore(time), notEqClosed()).fetch();
public List<Event> queryEventsByEndAtBeforeAndStatusOpen(LocalDateTime time) {
return queryFactory.selectFrom(event).where(endAtBefore(time), statusEq(OPEN)).fetch();
}

private BooleanExpression hostIdIn(List<Long> hostId) {
Expand All @@ -83,8 +83,8 @@ private BooleanExpression statusEq(EventStatus status) {
return event.status.eq(status);
}

private BooleanExpression notEqClosed() {
return event.status.eq(CLOSED).not();
private BooleanExpression statusNotEq(EventStatus status) {
return event.status.eq(status).not();
}

private BooleanExpression nameContains(String keyword) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package band.gosrock.domain.domains.event.service;

import static band.gosrock.domain.domains.event.domain.QEvent.event;

import band.gosrock.common.annotation.DomainService;
import band.gosrock.domain.domains.event.adaptor.EventAdaptor;
Expand Down Expand Up @@ -71,7 +70,7 @@ public Event updateEventStatus(Event event, EventStatus status) {
}

public List<Event> closeExpiredEventsEndAtBefore(LocalDateTime time) {
List<Event> events = eventAdaptor.queryEventsByEndAtBefore(time);
List<Event> events = eventAdaptor.queryEventsByEndAtBeforeAndStatusOpen(time);
events.forEach(event -> updateEventStatus(event, EventStatus.CLOSED));
eventRepository.saveAll(events);
return events;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public void validApproveStatePurchaseLimit(Order order) {

/** 이벤트가 열려있는 상태인지 */
public void validEventIsOpen(Event event) {
event.validateStatusOpen();
event.validateNotOpenStatus();
}

/** 아이템의 종류가 1종류인지. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void setUp() {
@Test
public void 카트_티켓팅_이벤트_상태검증_성공() {
// given
willDoNothing().given(event).validateStatusOpen();
willDoNothing().given(event).validateNotOpenStatus();
// when
cartValidator.validEventIsOpen(event);
// then
Expand All @@ -109,7 +109,7 @@ void setUp() {
@Test
public void 카트_티켓팅_이벤트_상태검증_실패() {
// given
willThrow(EventNotOpenException.class).given(event).validateStatusOpen();
willThrow(EventNotOpenException.class).given(event).validateNotOpenStatus();
// when
// then
assertThrows(EventNotOpenException.class, () -> cartValidator.validEventIsOpen(event));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ void setup() {
@Test
void 이벤트_종료로_상태변경_테스트() {
// given
ReflectionTestUtils.setField(event, "status", EventStatus.OPEN);
final EventStatus originalStatus = event.getStatus();
final EventStatus expectedStatus = EventStatus.CLOSED;
// when
Expand All @@ -118,14 +119,30 @@ void setup() {
// given
final EventStatus originalStatus = event.getStatus();
final EventStatus expectedStatus = EventStatus.OPEN;
final LocalDateTime startAt = LocalDateTime.now().plusMinutes(1);
// when
when(eventBasic.getStartAt()).thenReturn(startAt);
event.setEventBasic(eventBasic);
event.open();
// then
assertEquals(expectedStatus, event.getStatus());
assertNotEquals(originalStatus, expectedStatus);
assertThrows(AlreadyOpenStatusException.class, () -> event.open());
}

@Test
void 오픈_시간_이전인_이벤트는_오픈할수_없음() {
// given
final EventStatus originalStatus = event.getStatus();
final LocalDateTime startAt = LocalDateTime.now().minusMinutes(1);
// when
when(eventBasic.getStartAt()).thenReturn(startAt);
event.setEventBasic(eventBasic);
// then
assertThrows(EventOpenTimeExpiredException.class, () -> event.open());
assertEquals(originalStatus, event.getStatus());
}

@Test
void 이벤트_준비중으로_상태변경_테스트() {
// given
Expand Down
Loading

0 comments on commit 40ee07e

Please sign in to comment.