Skip to content

Commit

Permalink
feat: 수료 철회시 쿠폰 회수 이벤트 구현 (#857)
Browse files Browse the repository at this point in the history
* feat: 수료 철회시 쿠폰 회수 이벤트 구현

* rename: 메서드 이름 변경

* refactor: where 조건 순서 변경
  • Loading branch information
Sangwook02 authored Jan 30, 2025
1 parent 64acab1 commit 621c9a2
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.gdschongik.gdsc.domain.coupon.application;

import com.gdschongik.gdsc.domain.study.domain.StudyHistoriesCompletedEvent;
import com.gdschongik.gdsc.domain.study.domain.StudyHistoryCompletionWithdrawnEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
Expand All @@ -20,4 +21,10 @@ public void handleStudyHistoryCompletedEvent(StudyHistoriesCompletedEvent event)
log.info("[CouponEventHandler] 스터디 수료 이벤트 수신: studyHistoryIds={}", event.studyHistoryIds());
couponService.createAndIssueCouponByStudyHistories(event.studyHistoryIds());
}

@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void handleStudyHistoryCompletionWithdrawnEvent(StudyHistoryCompletionWithdrawnEvent event) {
log.info("[CouponEventHandler] 스터디 수료 철회 이벤트 수신: studyHistoryId={}", event.studyHistoryId());
couponService.revokeStudyCompletionCouponByStudyHistoryId(event.studyHistoryId());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gdschongik.gdsc.domain.coupon.application;

import static com.gdschongik.gdsc.domain.coupon.domain.CouponType.*;
import static com.gdschongik.gdsc.global.exception.ErrorCode.*;

import com.gdschongik.gdsc.domain.common.vo.Money;
Expand Down Expand Up @@ -109,7 +110,7 @@ public void createAndIssueCouponByStudyHistories(List<Long> studyHistoryIds) {
List<Member> students = memberRepository.findAllById(studentIds);
Study study = studyHistories.get(0).getStudy();

Coupon coupon = findOrCreate(CouponType.STUDY_COMPLETION, study);
Coupon coupon = findOrCreate(STUDY_COMPLETION, study);

List<IssuedCoupon> issuedCoupons = students.stream()
.map(student -> IssuedCoupon.create(coupon, student))
Expand All @@ -128,4 +129,20 @@ private Coupon findOrCreate(CouponType couponType, Study study) {
return couponRepository.save(coupon);
});
}

@Transactional
public void revokeStudyCompletionCouponByStudyHistoryId(long studyHistoryId) {
StudyHistory studyHistory = studyHistoryRepository
.findById(studyHistoryId)
.orElseThrow(() -> new CustomException(STUDY_HISTORY_NOT_FOUND));

IssuedCoupon issuedCoupon = issuedCouponRepository
.findUnrevokedIssuedStudyCoupon(STUDY_COMPLETION, studyHistory.getStudent(), studyHistory.getStudy())
.orElseThrow(() -> new CustomException(ISSUED_COUPON_NOT_FOUND));

issuedCoupon.revoke();
issuedCouponRepository.save(issuedCoupon);

log.info("[CouponService] 스터디 수료 쿠폰 회수: issuedCouponId={}", issuedCoupon.getId());
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package com.gdschongik.gdsc.domain.coupon.dao;

import com.gdschongik.gdsc.domain.coupon.domain.CouponType;
import com.gdschongik.gdsc.domain.coupon.domain.IssuedCoupon;
import com.gdschongik.gdsc.domain.coupon.dto.request.IssuedCouponQueryOption;
import com.gdschongik.gdsc.domain.member.domain.Member;
import com.gdschongik.gdsc.domain.study.domain.Study;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface IssuedCouponCustomRepository {

Page<IssuedCoupon> findAllIssuedCoupons(IssuedCouponQueryOption queryOption, Pageable pageable);

Optional<IssuedCoupon> findUnrevokedIssuedStudyCoupon(CouponType couponType, Member member, Study study);
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package com.gdschongik.gdsc.domain.coupon.dao;

import static com.gdschongik.gdsc.domain.coupon.domain.QCoupon.*;
import static com.gdschongik.gdsc.domain.coupon.domain.QIssuedCoupon.issuedCoupon;

import com.gdschongik.gdsc.domain.coupon.domain.CouponType;
import com.gdschongik.gdsc.domain.coupon.domain.IssuedCoupon;
import com.gdschongik.gdsc.domain.coupon.dto.request.IssuedCouponQueryOption;
import com.gdschongik.gdsc.domain.member.domain.Member;
import com.gdschongik.gdsc.domain.study.domain.Study;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -32,4 +37,16 @@ public Page<IssuedCoupon> findAllIssuedCoupons(IssuedCouponQueryOption queryOpti

return PageableExecutionUtils.getPage(fetch, pageable, countQuery::fetchOne);
}

@Override
public Optional<IssuedCoupon> findUnrevokedIssuedStudyCoupon(CouponType couponType, Member member, Study study) {
return Optional.ofNullable(queryFactory
.selectFrom(issuedCoupon)
.leftJoin(issuedCoupon.coupon, coupon)
.where(eqMember(member)
.and(coupon.study.eq(study))
.and(hasRevoked(false))
.and(coupon.couponType.eq(couponType)))
.fetchFirst());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static com.gdschongik.gdsc.domain.coupon.domain.QIssuedCoupon.issuedCoupon;

import com.gdschongik.gdsc.domain.coupon.dto.request.IssuedCouponQueryOption;
import com.gdschongik.gdsc.domain.member.domain.Member;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.dsl.BooleanExpression;

Expand All @@ -16,6 +17,10 @@ default BooleanExpression eqMemberName(String memberName) {
return memberName != null ? issuedCoupon.coupon.name.containsIgnoreCase(memberName) : null;
}

default BooleanExpression eqMember(Member member) {
return member != null ? issuedCoupon.member.eq(member) : null;
}

default BooleanExpression eqPhone(String phone) {
return phone != null ? issuedCoupon.member.phone.contains(phone.replaceAll("-", "")) : null;
}
Expand Down

0 comments on commit 621c9a2

Please sign in to comment.