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

refactor: 쿠폰, 알림 코드 개선 #180

Merged
merged 4 commits into from
Nov 29, 2023
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 @@ -73,7 +73,7 @@ public void issue() {
}
}

public void registerQueue(Long memberId, String couponName) {
public void registerQueue(String couponName, Long memberId) {
double registerTime = System.currentTimeMillis();
validateRegisterQueue(couponName);
couponManageRepository.addIfAbsentQueue(couponName, memberId, registerTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public static MyCouponResponse toMyResponse(CouponWallet couponWallet) {
Coupon coupon = couponWallet.getCoupon();

return MyCouponResponse.builder()
.walletId(couponWallet.getId())
.id(coupon.getId())
.name(coupon.getName())
.description(coupon.getDescription())
Expand Down
55 changes: 29 additions & 26 deletions src/main/java/com/moabam/api/application/coupon/CouponService.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.moabam.api.dto.coupon.CouponStatusRequest;
import com.moabam.api.dto.coupon.CreateCouponRequest;
import com.moabam.api.dto.coupon.MyCouponResponse;
import com.moabam.global.auth.model.AuthMember;
import com.moabam.global.common.util.ClockHolder;
import com.moabam.global.error.exception.BadRequestException;
import com.moabam.global.error.exception.ConflictException;
Expand All @@ -42,29 +41,47 @@ public class CouponService {
private final CouponWalletSearchRepository couponWalletSearchRepository;

@Transactional
public void create(AuthMember admin, CreateCouponRequest request) {
validateAdminRole(admin);
public void create(CreateCouponRequest request, Long adminId, Role role) {
validateAdminRole(role);
validateConflictName(request.name());
validateConflictStartAt(request.startAt());
validatePeriod(request.startAt(), request.openAt());

Coupon coupon = CouponMapper.toEntity(admin.id(), request);
Coupon coupon = CouponMapper.toEntity(adminId, request);

couponRepository.save(coupon);
}

@Transactional
public void use(Long memberId, Long couponWalletId) {
CouponWallet couponWallet = getWalletByIdAndMemberId(couponWalletId, memberId);
public void delete(Long couponId, Role role) {
validateAdminRole(role);

Coupon coupon = couponRepository.findById(couponId)
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON));

couponRepository.delete(coupon);
couponManageService.deleteQueue(coupon.getName());
}

@Transactional
public void use(Long couponWalletId, Long memberId) {
CouponWallet couponWallet = couponWalletSearchRepository.findByIdAndMemberId(couponWalletId, memberId)
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON_WALLET));
Coupon coupon = couponWallet.getCoupon();
BugType bugType = coupon.getType().getBugType();

if (coupon.getType().isDiscount()) {
throw new BadRequestException(ErrorMessage.INVALID_DISCOUNT_COUPON);
}

bugService.applyCoupon(memberId, bugType, coupon.getPoint());
couponWalletRepository.delete(couponWallet);
}

@Transactional
public void discount(Long memberId, Long couponWalletId) {
CouponWallet couponWallet = getWalletByIdAndMemberId(couponWalletId, memberId);
public void discount(Long couponWalletId, Long memberId) {
CouponWallet couponWallet = couponWalletSearchRepository.findByIdAndMemberId(couponWalletId, memberId)
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON_WALLET));
Coupon coupon = couponWallet.getCoupon();

if (!coupon.getType().isDiscount()) {
Expand All @@ -74,15 +91,6 @@ public void discount(Long memberId, Long couponWalletId) {
couponWalletRepository.delete(couponWallet);
}

@Transactional
public void delete(AuthMember admin, Long couponId) {
validateAdminRole(admin);
Coupon coupon = couponRepository.findById(couponId)
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON));
couponRepository.delete(coupon);
couponManageService.deleteQueue(coupon.getName());
}

public CouponResponse getById(Long couponId) {
Coupon coupon = couponRepository.findById(couponId)
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON));
Expand All @@ -97,18 +105,13 @@ public List<CouponResponse> getAllByStatus(CouponStatusRequest request) {
return CouponMapper.toResponses(coupons);
}

public List<MyCouponResponse> getWallet(Long couponId, AuthMember authMember) {
public List<MyCouponResponse> getAllByWalletIdAndMemberId(Long couponWalletId, Long memberId) {
List<CouponWallet> couponWallets =
couponWalletSearchRepository.findAllByCouponIdAndMemberId(couponId, authMember.id());
couponWalletSearchRepository.findAllByIdAndMemberId(couponWalletId, memberId);

return CouponMapper.toMyResponses(couponWallets);
}

public CouponWallet getWalletByIdAndMemberId(Long couponWalletId, Long memberId) {
return couponWalletSearchRepository.findByIdAndMemberId(couponWalletId, memberId)
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON_WALLET));
}

private void validatePeriod(LocalDate startAt, LocalDate openAt) {
LocalDate now = clockHolder.date();

Expand All @@ -121,8 +124,8 @@ private void validatePeriod(LocalDate startAt, LocalDate openAt) {
}
}

private void validateAdminRole(AuthMember admin) {
if (!admin.role().equals(Role.ADMIN)) {
private void validateAdminRole(Role role) {
if (!role.equals(Role.ADMIN)) {
throw new NotFoundException(ErrorMessage.MEMBER_NOT_FOUND);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import com.moabam.api.domain.room.Participant;
import com.moabam.api.domain.room.repository.ParticipantSearchRepository;
import com.moabam.api.infrastructure.fcm.FcmService;
import com.moabam.global.auth.model.AuthMember;
import com.moabam.global.common.util.ClockHolder;
import com.moabam.global.error.exception.ConflictException;
import com.moabam.global.error.exception.NotFoundException;
Expand All @@ -40,14 +39,14 @@ public class NotificationService {
private final ParticipantSearchRepository participantSearchRepository;

@Transactional
public void sendKnock(AuthMember member, Long targetId, Long roomId) {
public void sendKnock(Long roomId, Long targetId, Long memberId, String memberNickname) {
roomService.validateRoomById(roomId);
validateConflictKnock(member.id(), targetId, roomId);
validateConflictKnock(roomId, targetId, memberId);
String fcmToken = fcmService.findTokenByMemberId(targetId)
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_FCM_TOKEN));

fcmService.sendAsync(fcmToken, String.format(KNOCK_BODY, member.nickname()));
notificationRepository.saveKnock(member.id(), targetId, roomId);
fcmService.sendAsync(fcmToken, String.format(KNOCK_BODY, memberNickname));
notificationRepository.saveKnock(roomId, targetId, memberId);
}

public void sendCouponIssueResult(Long memberId, String couponName, String body) {
Expand All @@ -74,7 +73,7 @@ public List<Long> getMyKnockStatusInRoom(Long memberId, Long roomId, List<Partic
.toList();

Predicate<Long> knockPredicate = targetId ->
notificationRepository.existsKnockByKey(memberId, targetId, roomId);
notificationRepository.existsKnockByKey(roomId, targetId, memberId);

Map<Boolean, List<Long>> knockStatus = filteredParticipants.stream()
.map(Participant::getMemberId)
Expand All @@ -83,8 +82,8 @@ public List<Long> getMyKnockStatusInRoom(Long memberId, Long roomId, List<Partic
return knockStatus.get(true);
}

private void validateConflictKnock(Long memberId, Long targetId, Long roomId) {
if (notificationRepository.existsKnockByKey(memberId, targetId, roomId)) {
private void validateConflictKnock(Long roomId, Long targetId, Long memberId) {
if (notificationRepository.existsKnockByKey(roomId, targetId, memberId)) {
throw new ConflictException(ErrorMessage.CONFLICT_KNOCK);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void confirm(Long memberId, ConfirmPaymentRequest request) {
payment.confirm(response.paymentKey(), response.approvedAt());

if (payment.isCouponApplied()) {
couponService.discount(memberId, payment.getCouponWalletId());
couponService.discount(payment.getCouponWalletId(), memberId);
}
bugService.charge(memberId, payment.getProduct());
} catch (MoabamException exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ public class CouponWalletSearchRepository {

private final JPAQueryFactory jpaQueryFactory;

public List<CouponWallet> findAllByCouponIdAndMemberId(Long couponId, Long memberId) {
public List<CouponWallet> findAllByIdAndMemberId(Long couponWalletId, Long memberId) {
return jpaQueryFactory
.selectFrom(couponWallet)
.join(couponWallet.coupon, coupon).fetchJoin()
.where(
DynamicQuery.generateEq(couponId, couponWallet.coupon.id::eq),
DynamicQuery.generateEq(couponWalletId, couponWallet.id::eq),
DynamicQuery.generateEq(memberId, couponWallet.memberId::eq)
)
.fetch();
}

public Optional<CouponWallet> findByIdAndMemberId(Long id, Long memberId) {
public Optional<CouponWallet> findByIdAndMemberId(Long couponWalletId, Long memberId) {
return Optional.ofNullable(jpaQueryFactory
.selectFrom(couponWallet)
.join(couponWallet.coupon, coupon).fetchJoin()
.where(
couponWallet.id.eq(id),
couponWallet.id.eq(couponWalletId),
couponWallet.memberId.eq(memberId))
.fetchOne()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,27 @@
@RequiredArgsConstructor
public class NotificationRepository {

private static final String KNOCK_KEY = "room_%s_member_%s_knocks_%s";
private static final String KNOCK_KEY = "roomId=%s_targetId=%s_memberId=%s";
private static final long EXPIRE_KNOCK = 12;

private final ValueRedisRepository valueRedisRepository;

public void saveKnock(Long memberId, Long targetId, Long roomId) {
String knockKey =
String.format(KNOCK_KEY, requireNonNull(roomId), requireNonNull(memberId), requireNonNull(targetId));
public void saveKnock(Long roomId, Long targetId, Long memberId) {
String knockKey = String.format(
KNOCK_KEY,
requireNonNull(roomId),
requireNonNull(targetId),
requireNonNull(memberId));

valueRedisRepository.save(knockKey, BLANK, Duration.ofHours(EXPIRE_KNOCK));
}

public boolean existsKnockByKey(Long memberId, Long targetId, Long roomId) {
String knockKey =
String.format(KNOCK_KEY, requireNonNull(roomId), requireNonNull(memberId), requireNonNull(targetId));
public boolean existsKnockByKey(Long roomId, Long targetId, Long memberId) {
String knockKey = String.format(
KNOCK_KEY,
requireNonNull(roomId),
requireNonNull(targetId),
requireNonNull(memberId));

return valueRedisRepository.hasKey(requireNonNull(knockKey));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

@Builder
public record MyCouponResponse(
Long walletId,
Long id,
String name,
String description,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ public class FcmRepository {

private final ValueRedisRepository valueRedisRepository;

public void saveToken(Long memberId, String fcmToken) {
public void saveToken(String fcmToken, Long memberId) {
String tokenKey = String.valueOf(requireNonNull(memberId));

valueRedisRepository.save(
String.valueOf(requireNonNull(memberId)),
tokenKey,
requireNonNull(fcmToken),
Duration.ofDays(EXPIRE_FCM_TOKEN)
);
Duration.ofDays(EXPIRE_FCM_TOKEN));
}

public void deleteTokenByMemberId(Long memberId) {
Expand All @@ -33,8 +34,4 @@ public void deleteTokenByMemberId(Long memberId) {
public String findTokenByMemberId(Long memberId) {
return valueRedisRepository.get(String.valueOf(requireNonNull(memberId)));
}

public boolean existsTokenByMemberId(Long memberId) {
return valueRedisRepository.hasKey(String.valueOf(requireNonNull(memberId)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.Notification;
import com.moabam.global.auth.model.AuthMember;

import lombok.RequiredArgsConstructor;

Expand All @@ -18,16 +17,14 @@ public class FcmService {
private final FirebaseMessaging firebaseMessaging;
private final FcmRepository fcmRepository;

// TODO : 세연님 로그인 시, 해당 메서드 사용해서 해당 유저의 FCM TOKEN 저장하면 됩니다. Front와 상의 후 삭제예정
public void createToken(AuthMember authMember, String fcmToken) {
public void createToken(String fcmToken, Long memberId) {
if (fcmToken == null || fcmToken.isBlank()) {
return;
}

fcmRepository.saveToken(authMember.id(), fcmToken);
fcmRepository.saveToken(fcmToken, memberId);
}

// TODO : 세연님 로그아웃 시, 해당 메서드 사용해서 해당 유저의 FCM TOKEN 삭제하시면 됩니다. (이 코드는 원하시면 변경하셔도 됩니다.)
public void deleteTokenByMemberId(Long memberId) {
fcmRepository.deleteTokenByMemberId(memberId);
}
Expand Down
30 changes: 16 additions & 14 deletions src/main/java/com/moabam/api/presentation/CouponController.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ public class CouponController {

@PostMapping("/admins/coupons")
@ResponseStatus(HttpStatus.CREATED)
public void create(@Auth AuthMember admin, @Valid @RequestBody CreateCouponRequest request) {
couponService.create(admin, request);
public void create(@Valid @RequestBody CreateCouponRequest request, @Auth AuthMember admin) {
couponService.create(request, admin.id(), admin.role());
}

@DeleteMapping("/admins/coupons/{couponId}")
@ResponseStatus(HttpStatus.OK)
public void delete(@Auth AuthMember admin, @PathVariable("couponId") Long couponId) {
couponService.delete(admin, couponId);
public void delete(@PathVariable("couponId") Long couponId, @Auth AuthMember admin) {
couponService.delete(couponId, admin.role());
}

@GetMapping("/coupons/{couponId}")
Expand All @@ -55,22 +55,24 @@ public List<CouponResponse> getAllByStatus(@Valid @RequestBody CouponStatusReque
return couponService.getAllByStatus(request);
}

@PostMapping("/coupons")
@GetMapping({"/my-coupons", "/my-coupons/{couponWalletId}"})
@ResponseStatus(HttpStatus.OK)
public void registerQueue(@Auth AuthMember authMember, @RequestParam("couponName") String couponName) {
couponManageService.registerQueue(authMember.id(), couponName);
public List<MyCouponResponse> getAllByWalletIdAndMemberId(
@PathVariable(value = "couponWalletId", required = false) Long couponWalletId,
@Auth AuthMember authMember
) {
return couponService.getAllByWalletIdAndMemberId(couponWalletId, authMember.id());
}

@GetMapping({"/my-coupons", "/my-coupons/{couponId}"})
@PostMapping("/my-coupons/{couponWalletId}")
@ResponseStatus(HttpStatus.OK)
public List<MyCouponResponse> getWallet(@Auth AuthMember authMember,
@PathVariable(value = "couponId", required = false) Long couponId) {
return couponService.getWallet(couponId, authMember);
public void use(@PathVariable("couponWalletId") Long couponWalletId, @Auth AuthMember authMember) {
couponService.use(couponWalletId, authMember.id());
}

@PostMapping("/my-coupons/{couponWalletId}")
@PostMapping("/coupons")
@ResponseStatus(HttpStatus.OK)
public void use(@Auth AuthMember authMember, @PathVariable("couponWalletId") Long couponWalletId) {
couponService.use(authMember.id(), couponWalletId);
public void registerQueue(@RequestParam("couponName") String couponName, @Auth AuthMember authMember) {
couponManageService.registerQueue(couponName, authMember.id());
Copy link
Contributor

Choose a reason for hiding this comment

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

Q: 전부 회원의 AuthMember 위치가 변동 된 거 같은데 무슨 가독성 때문인가요?

Copy link
Member Author

@hongdosan hongdosan Nov 29, 2023

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 @@ -26,14 +26,17 @@ public class NotificationController {

@GetMapping("/rooms/{roomId}/members/{memberId}")
@ResponseStatus(HttpStatus.OK)
public void sendKnockNotification(@Auth AuthMember member, @PathVariable("roomId") Long roomId,
@PathVariable("memberId") Long memberId) {
notificationService.sendKnock(member, memberId, roomId);
public void sendKnock(
@PathVariable("roomId") Long roomId,
@PathVariable("memberId") Long memberId,
@Auth AuthMember authMember
) {
notificationService.sendKnock(roomId, memberId, authMember.id(), authMember.nickname());
}

@PostMapping
@ResponseStatus(HttpStatus.OK)
public void createFcmToken(@Auth AuthMember authMember, @RequestParam("fcmToken") String fcmToken) {
fcmService.createToken(authMember, fcmToken);
public void createFcmToken(@RequestParam("fcmToken") String fcmToken, @Auth AuthMember authMember) {
fcmService.createToken(fcmToken, authMember.id());
}
}
Loading