From d6173c574476dbf583a3926e214fda77a2f5d021 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=9D=B4=EC=9E=AC=EC=9B=90?= <jaewonlee.pro@gmail.com>
Date: Tue, 29 Oct 2024 00:17:33 +0900
Subject: [PATCH] =?UTF-8?q?Feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20?=
 =?UTF-8?q?=EB=B1=83=EC=A7=80=20=EB=B6=80=EC=97=AC=20=EA=B8=B0=EB=8A=A5=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#286)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../application/badge/BadgeEventHandler.java   | 18 ++++++++++++++++++
 .../runus/application/badge/BadgeService.java  | 18 +++++++++++++++---
 .../runus/domain/badge/BadgeRepository.java    |  4 ++++
 .../domain/badge/BadgeRepositoryImpl.java      | 12 ++++++++++++
 .../badge/JooqBadgeAchievementRepository.java  |  9 +++++++--
 .../jpa/badge/JpaBadgeRepository.java          | 11 +++++++++++
 6 files changed, 67 insertions(+), 5 deletions(-)
 create mode 100644 src/main/java/com/dnd/runus/application/badge/BadgeEventHandler.java
 create mode 100644 src/main/java/com/dnd/runus/infrastructure/persistence/jpa/badge/JpaBadgeRepository.java

diff --git a/src/main/java/com/dnd/runus/application/badge/BadgeEventHandler.java b/src/main/java/com/dnd/runus/application/badge/BadgeEventHandler.java
new file mode 100644
index 00000000..6b42c919
--- /dev/null
+++ b/src/main/java/com/dnd/runus/application/badge/BadgeEventHandler.java
@@ -0,0 +1,18 @@
+package com.dnd.runus.application.badge;
+
+import com.dnd.runus.application.member.event.SignupEvent;
+import com.dnd.runus.global.constant.BadgeType;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class BadgeEventHandler {
+    private final BadgeService badgeService;
+
+    @EventListener
+    public void handleSignupEvent(SignupEvent signupEvent) {
+        badgeService.achieveBadge(signupEvent.member(), BadgeType.PERSONAL_RECORD, 0);
+    }
+}
diff --git a/src/main/java/com/dnd/runus/application/badge/BadgeService.java b/src/main/java/com/dnd/runus/application/badge/BadgeService.java
index 73789eff..5f64fe4c 100644
--- a/src/main/java/com/dnd/runus/application/badge/BadgeService.java
+++ b/src/main/java/com/dnd/runus/application/badge/BadgeService.java
@@ -1,8 +1,7 @@
 package com.dnd.runus.application.badge;
 
-import com.dnd.runus.domain.badge.BadgeAchievementRepository;
-import com.dnd.runus.domain.badge.BadgeRepository;
-import com.dnd.runus.domain.badge.BadgeWithAchieveStatusAndAchievedAt;
+import com.dnd.runus.domain.badge.*;
+import com.dnd.runus.domain.member.Member;
 import com.dnd.runus.global.constant.BadgeType;
 import com.dnd.runus.presentation.v1.badge.dto.response.AchievedBadgesResponse;
 import com.dnd.runus.presentation.v1.badge.dto.response.AllBadgesListResponse;
@@ -26,6 +25,19 @@ public class BadgeService {
     private final BadgeAchievementRepository badgeAchievementRepository;
     private final BadgeRepository badgeRepository;
 
+    public void achieveBadge(Member member, BadgeType badgeType, int value) {
+        List<Badge> badges = badgeRepository.findByTypeAndRequiredValueLessThanEqual(badgeType, value);
+        if (badges.isEmpty()) {
+            return;
+        }
+
+        List<BadgeAchievement> badgeAchievements = badges.stream()
+                .map(badge -> new BadgeAchievement(badge, member))
+                .toList();
+
+        badgeAchievementRepository.saveAllIgnoreDuplicated(badgeAchievements);
+    }
+
     public AchievedBadgesResponse getAchievedBadges(long memberId) {
         return new AchievedBadgesResponse(badgeAchievementRepository.findByMemberIdWithBadge(memberId).stream()
                 .map(badgeAchievement -> new AchievedBadgesResponse.AchievedBadge(
diff --git a/src/main/java/com/dnd/runus/domain/badge/BadgeRepository.java b/src/main/java/com/dnd/runus/domain/badge/BadgeRepository.java
index 2b36d5d7..975a15e3 100644
--- a/src/main/java/com/dnd/runus/domain/badge/BadgeRepository.java
+++ b/src/main/java/com/dnd/runus/domain/badge/BadgeRepository.java
@@ -1,7 +1,11 @@
 package com.dnd.runus.domain.badge;
 
+import com.dnd.runus.global.constant.BadgeType;
+
 import java.util.List;
 
 public interface BadgeRepository {
+    List<Badge> findByTypeAndRequiredValueLessThanEqual(BadgeType badgeType, int requiredValue);
+
     List<BadgeWithAchieveStatusAndAchievedAt> findAllBadgesWithAchieveStatusByMemberId(long memberId);
 }
diff --git a/src/main/java/com/dnd/runus/infrastructure/persistence/domain/badge/BadgeRepositoryImpl.java b/src/main/java/com/dnd/runus/infrastructure/persistence/domain/badge/BadgeRepositoryImpl.java
index db3d5235..e8751e95 100644
--- a/src/main/java/com/dnd/runus/infrastructure/persistence/domain/badge/BadgeRepositoryImpl.java
+++ b/src/main/java/com/dnd/runus/infrastructure/persistence/domain/badge/BadgeRepositoryImpl.java
@@ -1,8 +1,12 @@
 package com.dnd.runus.infrastructure.persistence.domain.badge;
 
+import com.dnd.runus.domain.badge.Badge;
 import com.dnd.runus.domain.badge.BadgeRepository;
 import com.dnd.runus.domain.badge.BadgeWithAchieveStatusAndAchievedAt;
+import com.dnd.runus.global.constant.BadgeType;
 import com.dnd.runus.infrastructure.persistence.jooq.badge.JooqBadgeRepository;
+import com.dnd.runus.infrastructure.persistence.jpa.badge.JpaBadgeRepository;
+import com.dnd.runus.infrastructure.persistence.jpa.badge.entity.BadgeEntity;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Repository;
 
@@ -11,8 +15,16 @@
 @Repository
 @RequiredArgsConstructor
 public class BadgeRepositoryImpl implements BadgeRepository {
+    private final JpaBadgeRepository jpaBadgeRepository;
     private final JooqBadgeRepository jooqBadgeRepository;
 
+    @Override
+    public List<Badge> findByTypeAndRequiredValueLessThanEqual(BadgeType badgeType, int requiredValue) {
+        return jpaBadgeRepository.findByTypeAndRequiredValueLessThanEqual(badgeType, requiredValue).stream()
+                .map(BadgeEntity::toDomain)
+                .toList();
+    }
+
     @Override
     public List<BadgeWithAchieveStatusAndAchievedAt> findAllBadgesWithAchieveStatusByMemberId(long memberId) {
         return jooqBadgeRepository.findAllBadgesWithAchieveStatusByMemberId(memberId);
diff --git a/src/main/java/com/dnd/runus/infrastructure/persistence/jooq/badge/JooqBadgeAchievementRepository.java b/src/main/java/com/dnd/runus/infrastructure/persistence/jooq/badge/JooqBadgeAchievementRepository.java
index 66f47878..b43685a2 100644
--- a/src/main/java/com/dnd/runus/infrastructure/persistence/jooq/badge/JooqBadgeAchievementRepository.java
+++ b/src/main/java/com/dnd/runus/infrastructure/persistence/jooq/badge/JooqBadgeAchievementRepository.java
@@ -30,6 +30,7 @@ public List<BadgeAchievement.OnlyBadge> findByMemberIdWithBadge(long memberId) {
     }
 
     public void saveAllIgnoreDuplicated(List<BadgeAchievement> badgeAchievements) {
+        OffsetDateTime now = OffsetDateTime.now();
         dsl.batch(badgeAchievements.stream()
                         .map(badgeAchievement -> dsl.insertInto(BADGE_ACHIEVEMENT)
                                 .set(
@@ -38,8 +39,12 @@ public void saveAllIgnoreDuplicated(List<BadgeAchievement> badgeAchievements) {
                                 .set(
                                         BADGE_ACHIEVEMENT.MEMBER_ID,
                                         badgeAchievement.member().memberId())
-                                .set(BADGE_ACHIEVEMENT.CREATED_AT, badgeAchievement.createdAt())
-                                .set(BADGE_ACHIEVEMENT.UPDATED_AT, badgeAchievement.updatedAt())
+                                .set(
+                                        BADGE_ACHIEVEMENT.CREATED_AT,
+                                        badgeAchievement.createdAt() == null ? now : badgeAchievement.createdAt())
+                                .set(
+                                        BADGE_ACHIEVEMENT.UPDATED_AT,
+                                        badgeAchievement.updatedAt() == null ? now : badgeAchievement.updatedAt())
                                 .onConflictDoNothing())
                         .toList())
                 .execute();
diff --git a/src/main/java/com/dnd/runus/infrastructure/persistence/jpa/badge/JpaBadgeRepository.java b/src/main/java/com/dnd/runus/infrastructure/persistence/jpa/badge/JpaBadgeRepository.java
new file mode 100644
index 00000000..8eab0485
--- /dev/null
+++ b/src/main/java/com/dnd/runus/infrastructure/persistence/jpa/badge/JpaBadgeRepository.java
@@ -0,0 +1,11 @@
+package com.dnd.runus.infrastructure.persistence.jpa.badge;
+
+import com.dnd.runus.global.constant.BadgeType;
+import com.dnd.runus.infrastructure.persistence.jpa.badge.entity.BadgeEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+public interface JpaBadgeRepository extends JpaRepository<BadgeEntity, Long> {
+    List<BadgeEntity> findByTypeAndRequiredValueLessThanEqual(BadgeType badgeType, int requiredValue);
+}