CouponCommandServiceImpl.java
package com.deveagles.be15_deveagles_be.features.coupons.application.command;
import com.deveagles.be15_deveagles_be.common.exception.BusinessException;
import com.deveagles.be15_deveagles_be.common.exception.ErrorCode;
import com.deveagles.be15_deveagles_be.features.coupons.common.CouponDto;
import com.deveagles.be15_deveagles_be.features.coupons.domain.entity.Coupon;
import com.deveagles.be15_deveagles_be.features.coupons.domain.service.CouponCodeGenerator;
import com.deveagles.be15_deveagles_be.features.coupons.infrastructure.repository.CouponJpaRepository;
import com.deveagles.be15_deveagles_be.features.coupons.presentation.dto.request.DeleteCouponRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
@RequiredArgsConstructor
@Slf4j
public class CouponCommandServiceImpl implements CouponCommandService {
private final CouponJpaRepository couponJpaRepository;
private final CouponCodeGenerator couponCodeGenerator;
@Override
public CouponDto createCoupon(CreateCouponRequest command) {
log.info("쿠폰 생성 시작 - 쿠폰명: {}", command.getCouponTitle());
String couponCode = generateUniqueCouponCode();
Coupon coupon =
Coupon.builder()
.couponCode(couponCode)
.couponTitle(command.getCouponTitle())
.shopId(command.getShopId())
.staffId(command.getStaffId())
.primaryItemId(command.getPrimaryItemId())
.secondaryItemId(command.getSecondaryItemId())
.discountRate(command.getDiscountRate())
.expirationDate(command.getExpirationDate())
.isActive(command.getIsActive())
.build();
Coupon savedCoupon = couponJpaRepository.save(coupon);
log.info("쿠폰 생성 완료 - ID: {}, 쿠폰코드: {}", savedCoupon.getId(), savedCoupon.getCouponCode());
return CouponDto.from(savedCoupon);
}
private String generateUniqueCouponCode() {
String couponCode;
int attempts = 0;
final int maxAttempts = 10;
do {
couponCode = couponCodeGenerator.generateCouponCode();
attempts++;
if (attempts > maxAttempts) {
log.error("쿠폰 코드 생성 실패 - 최대 시도 횟수 초과");
throw new BusinessException(ErrorCode.INTERNAL_SERVER_ERROR, "쿠폰 코드 생성에 실패했습니다");
}
} while (couponJpaRepository.existsByCouponCodeAndNotDeleted(couponCode));
if (attempts > 1) {
log.info("쿠폰 코드 생성 - {}번 시도 후 성공: {}", attempts, couponCode);
}
return couponCode;
}
@Override
public void deleteCoupon(DeleteCouponRequest command) {
log.info("쿠폰 삭제 시작 - ID: {}, 매장ID: {}", command.getId(), command.getShopId());
Coupon coupon =
couponJpaRepository
.findByIdAndShopIdAndDeletedAtIsNull(command.getId(), command.getShopId())
.orElseThrow(
() -> {
log.warn("쿠폰을 찾을 수 없음 - ID: {}, 매장ID: {}", command.getId(), command.getShopId());
return new BusinessException(ErrorCode.COUPON_NOT_FOUND);
});
if (coupon.isDeleted()) {
log.warn("이미 삭제된 쿠폰 - ID: {}, 매장ID: {}", command.getId(), command.getShopId());
throw new BusinessException(ErrorCode.COUPON_ALREADY_DELETED);
}
coupon.softDelete();
couponJpaRepository.save(coupon);
log.info("쿠폰 삭제 완료 - ID: {}, 매장ID: {}", command.getId(), command.getShopId());
}
@Override
public CouponDto toggleCouponStatus(Long couponId, Long shopId) {
log.info("쿠폰 상태 토글 시작 - ID: {}, 매장ID: {}", couponId, shopId);
Coupon coupon =
couponJpaRepository
.findByIdAndShopIdAndDeletedAtIsNull(couponId, shopId)
.orElseThrow(
() -> {
log.warn("쿠폰을 찾을 수 없음 - ID: {}, 매장ID: {}", couponId, shopId);
return new BusinessException(ErrorCode.COUPON_NOT_FOUND);
});
if (coupon.isDeleted()) {
log.warn("삭제된 쿠폰 상태 변경 시도 - ID: {}, 매장ID: {}", couponId, shopId);
throw new BusinessException(ErrorCode.DELETED_COUPON_OPERATION_NOT_ALLOWED);
}
if (coupon.getIsActive()) {
coupon.deactivate();
log.info("쿠폰 비활성화 완료 - ID: {}, 매장ID: {}", couponId, shopId);
} else {
coupon.activate();
log.info("쿠폰 활성화 완료 - ID: {}, 매장ID: {}", couponId, shopId);
}
Coupon savedCoupon = couponJpaRepository.save(coupon);
return CouponDto.from(savedCoupon);
}
}