From 02d5b8bd7784fb555afe1e8f9d891a153903bda6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=AC=EC=9E=AC=EC=97=BD?= Date: Mon, 9 Jun 2025 02:28:19 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=EC=82=AC=EC=9E=A5/=EC=95=8C?= =?UTF-8?q?=EB=B0=94=EC=83=9D=20FAQ=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C=20(#110)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/faq/BossFaqController.java | 23 ++++++++++++++++ .../controller/faq/StaffFaqController.java | 23 ++++++++++++++++ .../app/api/facade/faq/BossFaqFacade.java | 23 ++++++++++++++++ .../app/api/facade/faq/StaffFaqFacade.java | 23 ++++++++++++++++ .../app/common/exception/CustomErrorInfo.java | 1 + .../app/domain/repository/FaqRepository.java | 13 +++++++++ .../app/domain/service/faq/FaqService.java | 25 +++++++++++++++++ .../mangoboss/app/dto/faq/FaqResponse.java | 22 +++++++++++++++ .../infra/persistence/FaqRepositoryImpl.java | 27 +++++++++++++++++++ 9 files changed, 180 insertions(+) create mode 100644 app/src/main/java/com/mangoboss/app/api/controller/faq/BossFaqController.java create mode 100644 app/src/main/java/com/mangoboss/app/api/controller/faq/StaffFaqController.java create mode 100644 app/src/main/java/com/mangoboss/app/api/facade/faq/BossFaqFacade.java create mode 100644 app/src/main/java/com/mangoboss/app/api/facade/faq/StaffFaqFacade.java create mode 100644 app/src/main/java/com/mangoboss/app/domain/repository/FaqRepository.java create mode 100644 app/src/main/java/com/mangoboss/app/domain/service/faq/FaqService.java create mode 100644 app/src/main/java/com/mangoboss/app/dto/faq/FaqResponse.java create mode 100644 app/src/main/java/com/mangoboss/app/infra/persistence/FaqRepositoryImpl.java diff --git a/app/src/main/java/com/mangoboss/app/api/controller/faq/BossFaqController.java b/app/src/main/java/com/mangoboss/app/api/controller/faq/BossFaqController.java new file mode 100644 index 00000000..b98ba27d --- /dev/null +++ b/app/src/main/java/com/mangoboss/app/api/controller/faq/BossFaqController.java @@ -0,0 +1,23 @@ +package com.mangoboss.app.api.controller.faq; + +import com.mangoboss.app.api.facade.faq.BossFaqFacade; +import com.mangoboss.app.dto.ListWrapperResponse; +import com.mangoboss.app.dto.faq.FaqResponse; +import com.mangoboss.storage.faq.FaqCategory; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/boss/faq") +@RequiredArgsConstructor +@PreAuthorize("hasRole('BOSS')") +public class BossFaqController { + + private final BossFaqFacade bossFaqFacade; + + @GetMapping + public ListWrapperResponse getFaqs(@RequestParam(value = "category", defaultValue = "ALL") FaqCategory category) { + return ListWrapperResponse.of(bossFaqFacade.getFaqs(category)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mangoboss/app/api/controller/faq/StaffFaqController.java b/app/src/main/java/com/mangoboss/app/api/controller/faq/StaffFaqController.java new file mode 100644 index 00000000..b19618bc --- /dev/null +++ b/app/src/main/java/com/mangoboss/app/api/controller/faq/StaffFaqController.java @@ -0,0 +1,23 @@ +package com.mangoboss.app.api.controller.faq; + +import com.mangoboss.app.api.facade.faq.StaffFaqFacade; +import com.mangoboss.app.dto.ListWrapperResponse; +import com.mangoboss.app.dto.faq.FaqResponse; +import com.mangoboss.storage.faq.FaqCategory; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/staff/faq") +@RequiredArgsConstructor +@PreAuthorize("hasRole('STAFF')") +public class StaffFaqController { + + private final StaffFaqFacade staffFaqFacade; + + @GetMapping + public ListWrapperResponse getFaqs(@RequestParam(value = "category", defaultValue = "ALL") FaqCategory category) { + return ListWrapperResponse.of(staffFaqFacade.getFaqs(category)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mangoboss/app/api/facade/faq/BossFaqFacade.java b/app/src/main/java/com/mangoboss/app/api/facade/faq/BossFaqFacade.java new file mode 100644 index 00000000..0f05d787 --- /dev/null +++ b/app/src/main/java/com/mangoboss/app/api/facade/faq/BossFaqFacade.java @@ -0,0 +1,23 @@ +package com.mangoboss.app.api.facade.faq; + +import com.mangoboss.app.domain.service.faq.FaqService; +import com.mangoboss.app.dto.faq.FaqResponse; +import com.mangoboss.storage.faq.FaqCategory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@RequiredArgsConstructor +public class BossFaqFacade { + + private final FaqService faqService; + + public List getFaqs(final FaqCategory category) { + return faqService.getFaqs(category).stream() + .map(FaqResponse::fromEntity) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mangoboss/app/api/facade/faq/StaffFaqFacade.java b/app/src/main/java/com/mangoboss/app/api/facade/faq/StaffFaqFacade.java new file mode 100644 index 00000000..f8bb8654 --- /dev/null +++ b/app/src/main/java/com/mangoboss/app/api/facade/faq/StaffFaqFacade.java @@ -0,0 +1,23 @@ +package com.mangoboss.app.api.facade.faq; + +import com.mangoboss.app.domain.service.faq.FaqService; +import com.mangoboss.app.dto.faq.FaqResponse; +import com.mangoboss.storage.faq.FaqCategory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@RequiredArgsConstructor +public class StaffFaqFacade { + + private final FaqService faqService; + + public List getFaqs(final FaqCategory category) { + return faqService.getFaqs(category).stream() + .map(FaqResponse::fromEntity) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mangoboss/app/common/exception/CustomErrorInfo.java b/app/src/main/java/com/mangoboss/app/common/exception/CustomErrorInfo.java index 61c6bd6b..b70fe9cf 100644 --- a/app/src/main/java/com/mangoboss/app/common/exception/CustomErrorInfo.java +++ b/app/src/main/java/com/mangoboss/app/common/exception/CustomErrorInfo.java @@ -97,6 +97,7 @@ public enum CustomErrorInfo { SUBSCRIPTION_NOT_FOUND(404, "구독 정보를 찾을 수 없습니다.", 404022), PAYROLL_SETTING_NOT_FOUND(404, "해당 매장의 급여 설정을 찾을 수 없습니다.", 404023), BILLING_CARD_NOT_REGISTERED(404, "결제수단이 등록되어 있지 않습니다.", 404024), + FAQ_NOT_FOUND(404, "FAQ를 찾을 수 없습니다.", 404025), // 405 Method Not Allowed METHOD_NOT_ALLOWED(405, "HTTP 메서드가 잘못되었습니다.", 405001), diff --git a/app/src/main/java/com/mangoboss/app/domain/repository/FaqRepository.java b/app/src/main/java/com/mangoboss/app/domain/repository/FaqRepository.java new file mode 100644 index 00000000..406cd33c --- /dev/null +++ b/app/src/main/java/com/mangoboss/app/domain/repository/FaqRepository.java @@ -0,0 +1,13 @@ +package com.mangoboss.app.domain.repository; + + +import com.mangoboss.storage.faq.FaqEntity; +import com.mangoboss.storage.faq.FaqCategory; + +import java.util.List; + +public interface FaqRepository { + List findAll(); + + List findByCategory(FaqCategory category); +} diff --git a/app/src/main/java/com/mangoboss/app/domain/service/faq/FaqService.java b/app/src/main/java/com/mangoboss/app/domain/service/faq/FaqService.java new file mode 100644 index 00000000..4aec0e51 --- /dev/null +++ b/app/src/main/java/com/mangoboss/app/domain/service/faq/FaqService.java @@ -0,0 +1,25 @@ +package com.mangoboss.app.domain.service.faq; + +import com.mangoboss.app.domain.repository.FaqRepository; +import com.mangoboss.storage.faq.FaqEntity; +import com.mangoboss.storage.faq.FaqCategory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class FaqService { + + private final FaqRepository faqRepository; + + public List getFaqs(final FaqCategory category) { + if (category == FaqCategory.ALL) { + return faqRepository.findAll(); + } + return faqRepository.findByCategory(category); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mangoboss/app/dto/faq/FaqResponse.java b/app/src/main/java/com/mangoboss/app/dto/faq/FaqResponse.java new file mode 100644 index 00000000..0751195b --- /dev/null +++ b/app/src/main/java/com/mangoboss/app/dto/faq/FaqResponse.java @@ -0,0 +1,22 @@ +package com.mangoboss.app.dto.faq; + +import com.mangoboss.storage.faq.FaqCategory; +import com.mangoboss.storage.faq.FaqEntity; +import lombok.Builder; + +@Builder +public record FaqResponse( + Long id, + FaqCategory category, + String question, + String answer +) { + public static FaqResponse fromEntity(final FaqEntity entity) { + return FaqResponse.builder() + .id(entity.getId()) + .category(entity.getCategory()) + .question(entity.getQuestion()) + .answer(entity.getAnswer()) + .build(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mangoboss/app/infra/persistence/FaqRepositoryImpl.java b/app/src/main/java/com/mangoboss/app/infra/persistence/FaqRepositoryImpl.java new file mode 100644 index 00000000..7e480d40 --- /dev/null +++ b/app/src/main/java/com/mangoboss/app/infra/persistence/FaqRepositoryImpl.java @@ -0,0 +1,27 @@ +package com.mangoboss.app.infra.persistence; + +import com.mangoboss.app.domain.repository.FaqRepository; +import com.mangoboss.storage.faq.FaqCategory; +import com.mangoboss.storage.faq.FaqEntity; +import com.mangoboss.storage.faq.FaqJpaRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@RequiredArgsConstructor +public class FaqRepositoryImpl implements FaqRepository { + + private final FaqJpaRepository faqJpaRepository; + + @Override + public List findAll() { + return faqJpaRepository.findAll(); + } + + @Override + public List findByCategory(FaqCategory category) { + return faqJpaRepository.findByCategory(category); + } +} From 05591629ea2c1cf3ca8aa76dcff47d7e619f05da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=AC=EC=9E=AC=EC=97=BD?= Date: Mon, 9 Jun 2025 02:39:28 +0900 Subject: [PATCH 2/7] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9E=A5=20=EA=B5=AC?= =?UTF-8?q?=EB=8F=85=20=ED=98=84=ED=99=A9,=20=EA=B2=B0=EC=A0=9C=20?= =?UTF-8?q?=EC=88=98=EB=8B=A8=20=EC=97=86=EC=9D=84=20=EB=95=8C=20null=20DT?= =?UTF-8?q?O=20=EB=B0=98=ED=99=98=20(#122)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../facade/subscription/SubscriptionFacade.java | 8 ++++++++ .../domain/repository/SubscriptionRepository.java | 4 +++- .../app/domain/service/billing/BillingService.java | 14 +++++++++----- .../service/subscription/SubscriptionService.java | 13 +++++++------ .../persistence/SubscriptionRepositoryImpl.java | 9 ++++----- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/mangoboss/app/api/facade/subscription/SubscriptionFacade.java b/app/src/main/java/com/mangoboss/app/api/facade/subscription/SubscriptionFacade.java index d012d9dd..1d176f2a 100644 --- a/app/src/main/java/com/mangoboss/app/api/facade/subscription/SubscriptionFacade.java +++ b/app/src/main/java/com/mangoboss/app/api/facade/subscription/SubscriptionFacade.java @@ -24,6 +24,14 @@ public void createOrReplaceSubscription(Long bossId, SubscriptionCreateRequest r public SubscriptionResponse getSubscription(Long bossId) { final var subscription = subscriptionService.getSubscription(bossId); + if (subscription == null) { + return SubscriptionResponse.builder() + .planType(null) + .startedAt(null) + .expiredAt(null) + .nextPaymentDate(null) + .build(); + } return SubscriptionResponse.fromEntity(subscription); } diff --git a/app/src/main/java/com/mangoboss/app/domain/repository/SubscriptionRepository.java b/app/src/main/java/com/mangoboss/app/domain/repository/SubscriptionRepository.java index 0a155d9a..e826abf1 100644 --- a/app/src/main/java/com/mangoboss/app/domain/repository/SubscriptionRepository.java +++ b/app/src/main/java/com/mangoboss/app/domain/repository/SubscriptionRepository.java @@ -2,9 +2,11 @@ import com.mangoboss.storage.subscription.SubscriptionEntity; +import java.util.Optional; + public interface SubscriptionRepository { void save(SubscriptionEntity subscriptionEntity); - SubscriptionEntity findByBossId(Long bossId); + Optional findByBossId(Long bossId); void delete(SubscriptionEntity subscriptionEntity); boolean existsByBossId(Long bossId); } \ No newline at end of file diff --git a/app/src/main/java/com/mangoboss/app/domain/service/billing/BillingService.java b/app/src/main/java/com/mangoboss/app/domain/service/billing/BillingService.java index 7adac356..c8546a2c 100644 --- a/app/src/main/java/com/mangoboss/app/domain/service/billing/BillingService.java +++ b/app/src/main/java/com/mangoboss/app/domain/service/billing/BillingService.java @@ -74,11 +74,15 @@ public void validateBillingExists(Long bossId) { } public BillingCardInfoResponse getBillingCardInfo(Long bossId) { - BillingEntity billing = billingRepository.findByBossId(bossId) - .orElseThrow(() -> new CustomException(CustomErrorInfo.BILLING_NOT_FOUND)); - - if (billing.getBillingKey() == null || billing.getCardData() == null) { - throw new CustomException(CustomErrorInfo.BILLING_CARD_NOT_REGISTERED); + BillingEntity billing = billingRepository.findByBossId(bossId).orElse(null); + + if (billing == null || billing.getBillingKey() == null || billing.getCardData() == null) { + return BillingCardInfoResponse.builder() + .cardCompany(null) + .cardNumber(null) + .cardType(null) + .ownerType(null) + .build(); } Map cardMap = JsonConverter.fromJson( diff --git a/app/src/main/java/com/mangoboss/app/domain/service/subscription/SubscriptionService.java b/app/src/main/java/com/mangoboss/app/domain/service/subscription/SubscriptionService.java index 5bc46724..eb75c94a 100644 --- a/app/src/main/java/com/mangoboss/app/domain/service/subscription/SubscriptionService.java +++ b/app/src/main/java/com/mangoboss/app/domain/service/subscription/SubscriptionService.java @@ -1,5 +1,7 @@ package com.mangoboss.app.domain.service.subscription; +import com.mangoboss.app.common.exception.CustomErrorInfo; +import com.mangoboss.app.common.exception.CustomException; import com.mangoboss.app.domain.repository.SubscriptionOrderRepository; import com.mangoboss.app.dto.subscription.response.SubscriptionOrderResponse; import com.mangoboss.storage.subscription.PlanType; @@ -22,21 +24,20 @@ public class SubscriptionService { @Transactional public void createOrReplaceSubscription(Long bossId, PlanType planType) { - if (subscriptionRepository.existsByBossId(bossId)) { - SubscriptionEntity existing = subscriptionRepository.findByBossId(bossId); - subscriptionRepository.delete(existing); - } + subscriptionRepository.findByBossId(bossId).ifPresent(subscriptionRepository::delete); + SubscriptionEntity subscription = SubscriptionEntity.create(bossId, planType); subscriptionRepository.save(subscription); } public SubscriptionEntity getSubscription(Long bossId) { - return subscriptionRepository.findByBossId(bossId); + return subscriptionRepository.findByBossId(bossId).orElse(null); } @Transactional public void deleteSubscription(Long bossId) { - SubscriptionEntity subscription = subscriptionRepository.findByBossId(bossId); + SubscriptionEntity subscription = subscriptionRepository.findByBossId(bossId) + .orElseThrow(() -> new CustomException(CustomErrorInfo.SUBSCRIPTION_NOT_FOUND)); subscriptionRepository.delete(subscription); } diff --git a/app/src/main/java/com/mangoboss/app/infra/persistence/SubscriptionRepositoryImpl.java b/app/src/main/java/com/mangoboss/app/infra/persistence/SubscriptionRepositoryImpl.java index de3cd533..c81f3b88 100644 --- a/app/src/main/java/com/mangoboss/app/infra/persistence/SubscriptionRepositoryImpl.java +++ b/app/src/main/java/com/mangoboss/app/infra/persistence/SubscriptionRepositoryImpl.java @@ -1,13 +1,13 @@ package com.mangoboss.app.infra.persistence; -import com.mangoboss.app.common.exception.CustomErrorInfo; -import com.mangoboss.app.common.exception.CustomException; import com.mangoboss.app.domain.repository.SubscriptionRepository; import com.mangoboss.storage.subscription.SubscriptionEntity; import com.mangoboss.storage.subscription.SubscriptionJpaRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository @RequiredArgsConstructor public class SubscriptionRepositoryImpl implements SubscriptionRepository { @@ -19,9 +19,8 @@ public void save(SubscriptionEntity subscriptionEntity) { } @Override - public SubscriptionEntity findByBossId(Long bossId) { - return subscriptionJpaRepository.findByBossId(bossId) - .orElseThrow(() -> new CustomException(CustomErrorInfo.SUBSCRIPTION_NOT_FOUND)); + public Optional findByBossId(Long bossId) { + return subscriptionJpaRepository.findByBossId(bossId); } @Override From 9bdc49044a691350a65efe5b50abc320316e2253 Mon Sep 17 00:00:00 2001 From: hyunzzii Date: Mon, 9 Jun 2025 03:54:35 +0900 Subject: [PATCH 3/7] =?UTF-8?q?fix:=20cd-dev.yml=20sentry=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EB=B3=80=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd-dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cd-dev.yml b/.github/workflows/cd-dev.yml index dfd3a157..3fb3745d 100644 --- a/.github/workflows/cd-dev.yml +++ b/.github/workflows/cd-dev.yml @@ -242,6 +242,8 @@ jobs: echo "AWS_KMS_KEY_ID=${{ secrets.AWS_KMS_KEY_ID }}" >> .env echo "NOTIFICATION_MAX_RETRY=${{ secrets.NOTIFICATION_MAX_RETRY }}" >> .env echo "TOSS_PAYMENT_SECRET_KEY=${{ secrets.TOSS_PAYMENT_SECRET_KEY }}" >> .env + echo "SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env + echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> .env echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin docker compose down -v From 4bf71919463b548d1076c48f427afac11b8ef79f Mon Sep 17 00:00:00 2001 From: hyunzzii Date: Mon, 9 Jun 2025 04:07:30 +0900 Subject: [PATCH 4/7] =?UTF-8?q?fix:=20cd-dev.yml=20sentry=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EB=B3=80=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd-dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cd-dev.yml b/.github/workflows/cd-dev.yml index 3fb3745d..2d9956ea 100644 --- a/.github/workflows/cd-dev.yml +++ b/.github/workflows/cd-dev.yml @@ -141,6 +141,8 @@ jobs: echo "AWS_S3_PUBLIC_BASE_URL=${{ secrets.AWS_S3_PUBLIC_BASE_URL }}" >> .env echo "FRONTEND_URL=${{ secrets.FRONTEND_URL }}" >> .env echo "TOSS_PAYMENT_SECRET_KEY=${{ secrets.TOSS_PAYMENT_SECRET_KEY }}" >> .env + echo "SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env + echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> .env echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin From 54af4136d0033c1e8f7932332f6958655b269d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=AC=EC=9E=AC=EC=97=BD?= Date: Mon, 9 Jun 2025 05:22:47 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EB=B0=9C=20(#128)=20?= =?UTF-8?q?-=20=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83=EC=8B=9C=20refresh-tok?= =?UTF-8?q?en=20Redis=EC=97=90=20=EB=B8=94=EB=9E=99=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=A1=9C=20=EB=B3=B4=EA=B4=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/auth/AuthController.java | 9 ++++---- .../app/api/facade/auth/AuthFacade.java | 5 +++++ .../app/common/exception/CustomErrorInfo.java | 1 + .../mangoboss/app/common/util/JwtUtil.java | 18 ++++++++++++++++ .../app/domain/service/auth/AuthService.java | 21 +++++++++++++++++++ 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/mangoboss/app/api/controller/auth/AuthController.java b/app/src/main/java/com/mangoboss/app/api/controller/auth/AuthController.java index f4e6557c..3e553d0d 100644 --- a/app/src/main/java/com/mangoboss/app/api/controller/auth/AuthController.java +++ b/app/src/main/java/com/mangoboss/app/api/controller/auth/AuthController.java @@ -2,10 +2,7 @@ import com.mangoboss.app.dto.auth.response.JwtResponse; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import com.mangoboss.app.api.facade.auth.AuthFacade; import com.mangoboss.app.dto.auth.requeset.LoginRequest; @@ -29,4 +26,8 @@ public JwtResponse socialLogin(@RequestBody LoginRequest loginRequest) { return authFacade.socialLogin(loginRequest); } + @PostMapping("/logout") + public void logout(@RequestHeader("X-Refresh-Token") String refreshToken) { + authFacade.logout(refreshToken); + } } diff --git a/app/src/main/java/com/mangoboss/app/api/facade/auth/AuthFacade.java b/app/src/main/java/com/mangoboss/app/api/facade/auth/AuthFacade.java index 1e6ec4f6..272a9180 100644 --- a/app/src/main/java/com/mangoboss/app/api/facade/auth/AuthFacade.java +++ b/app/src/main/java/com/mangoboss/app/api/facade/auth/AuthFacade.java @@ -19,6 +19,7 @@ public class AuthFacade { private final AuthService authService; public JwtResponse reissueAccessToken(final RefreshTokenRequest refreshTokenRequest) { + authService.validateNotBlacklisted(refreshTokenRequest.refreshToken()); final String refreshToken = refreshTokenRequest.refreshToken(); final Long userId = authService.validateAndExtractIdFromRefreshToken(refreshToken); final UserEntity user = userService.getUserById(userId); @@ -30,4 +31,8 @@ public JwtResponse socialLogin(final LoginRequest loginRequest) { final UserEntity user = userService.getOrCreateUser(kakaoUserInfo); return authService.generateToken(user); } + + public void logout(final String refreshToken) { + authService.logout(refreshToken); + } } diff --git a/app/src/main/java/com/mangoboss/app/common/exception/CustomErrorInfo.java b/app/src/main/java/com/mangoboss/app/common/exception/CustomErrorInfo.java index b70fe9cf..28245d67 100644 --- a/app/src/main/java/com/mangoboss/app/common/exception/CustomErrorInfo.java +++ b/app/src/main/java/com/mangoboss/app/common/exception/CustomErrorInfo.java @@ -57,6 +57,7 @@ public enum CustomErrorInfo { INVALID_TOKEN(401, "유효하지 않은 토큰입니다.", 401003), EXPIRED_TOKEN(401, "토큰이 만료되었습니다.", 401004), UNSUPPORTED_TOKEN(401, "지원되지 않는 토큰입니다.", 401005), + INVALID_REFRESH_TOKEN(401, "블랙리스트에 등록된 리프레시 토큰입니다.", 401006), // 403 FORBIDDEN NOT_STORE_BOSS(403, "이 매장의 사장이 아닙니다.", 403001), diff --git a/app/src/main/java/com/mangoboss/app/common/util/JwtUtil.java b/app/src/main/java/com/mangoboss/app/common/util/JwtUtil.java index fbdf7072..f51223da 100644 --- a/app/src/main/java/com/mangoboss/app/common/util/JwtUtil.java +++ b/app/src/main/java/com/mangoboss/app/common/util/JwtUtil.java @@ -106,4 +106,22 @@ public Claims parseClaims(final String accessToken) { return e.getClaims(); } } + + public long getRefreshTokenRemainingExpiration(final String refreshToken) { + Claims claims = parseClaims(refreshToken, false); + return claims.getExpiration().getTime() - System.currentTimeMillis(); + } + + private Claims parseClaims(final String token, final boolean isAccessToken) { + try { + SecretKey secret = isAccessToken ? accessSecret : refreshSecret; + return Jwts.parserBuilder() + .setSigningKey(secret) + .build() + .parseClaimsJws(token) + .getBody(); + } catch (ExpiredJwtException e) { + return e.getClaims(); // 만료된 토큰일 경우에도 claims 추출 가능 + } + } } diff --git a/app/src/main/java/com/mangoboss/app/domain/service/auth/AuthService.java b/app/src/main/java/com/mangoboss/app/domain/service/auth/AuthService.java index 6de057e9..4315c318 100644 --- a/app/src/main/java/com/mangoboss/app/domain/service/auth/AuthService.java +++ b/app/src/main/java/com/mangoboss/app/domain/service/auth/AuthService.java @@ -10,14 +10,18 @@ import com.mangoboss.storage.user.UserEntity; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; +import java.time.Duration; + @Service @RequiredArgsConstructor @Slf4j public class AuthService { private final JwtUtil jwtUtil; private final KakaoSocialLogin kakaoSocialLogin; + private final StringRedisTemplate redisTemplate; public KakaoUserInfo socialLogin(final LoginRequest loginRequest) { final String kakaoAccessToken = kakaoSocialLogin.requestKakaoAccessToken(loginRequest); @@ -42,4 +46,21 @@ public JwtResponse generateToken(final UserEntity user){ .refreshToken(refreshToken) .build(); } + + public void logout(final String refreshToken) { + final long remainingMillis = jwtUtil.getRefreshTokenRemainingExpiration(refreshToken); + final String redisKey = generateBlacklistKey(refreshToken); + redisTemplate.opsForValue().set(redisKey, "LOGOUT", Duration.ofMillis(remainingMillis)); + } + + public void validateNotBlacklisted(final String refreshToken) { + final String redisKey = generateBlacklistKey(refreshToken); + if (Boolean.TRUE.equals(redisTemplate.hasKey(redisKey))) { + throw new CustomException(CustomErrorInfo.INVALID_REFRESH_TOKEN); + } + } + + private String generateBlacklistKey(final String refreshToken) { + return "auth:logout:refresh:" + refreshToken; + } } From bebd1ba37c1e31a555af9de24fee5b42e7659b2b Mon Sep 17 00:00:00 2001 From: hyunzzii Date: Mon, 9 Jun 2025 11:21:24 +0900 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20notificationEntity=EC=97=90=20metaI?= =?UTF-8?q?d=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/NotificationEntity.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/storage/src/main/java/com/mangoboss/storage/notification/NotificationEntity.java b/storage/src/main/java/com/mangoboss/storage/notification/NotificationEntity.java index 9c045637..054360da 100644 --- a/storage/src/main/java/com/mangoboss/storage/notification/NotificationEntity.java +++ b/storage/src/main/java/com/mangoboss/storage/notification/NotificationEntity.java @@ -35,7 +35,7 @@ public class NotificationEntity extends BaseTimeEntity { @Column(length = 2083) private String imageUrl; - @Column( nullable = false) + @Column(nullable = false) private String clickUrl; @Enumerated(EnumType.STRING) @@ -49,6 +49,8 @@ public class NotificationEntity extends BaseTimeEntity { @Column(nullable = false) private int retryCount; + private Long metaId; + @Builder private NotificationEntity( final Long userId, @@ -60,7 +62,8 @@ private NotificationEntity( final String clickUrl, final NotificationType type, final SendStatus sendStatus, - final int retryCount + final int retryCount, + final Long metaId ) { this.userId = userId; this.storeId = storeId; @@ -72,6 +75,7 @@ private NotificationEntity( this.type = type; this.sendStatus = sendStatus; this.retryCount = retryCount; + this.metaId = metaId; } public static NotificationEntity create( @@ -95,6 +99,33 @@ public static NotificationEntity create( .type(type) .sendStatus(SendStatus.PENDING) .retryCount(0) + .metaId(null) + .build(); + } + + public static NotificationEntity createWithMetaId( + final Long userId, + final Long storeId, + final String title, + final String content, + final String imageUrl, + final String clickUrl, + final NotificationType type, + final String targetToken, + final Long metaId + ) { + return NotificationEntity.builder() + .userId(userId) + .storeId(storeId) + .targetToken(targetToken) + .title(title) + .content(content) + .imageUrl(imageUrl) + .clickUrl(clickUrl) + .type(type) + .sendStatus(SendStatus.PENDING) + .retryCount(0) + .metaId(metaId) .build(); } From d80c06694cad05d3c11692069fb001ae24c9ed73 Mon Sep 17 00:00:00 2001 From: hyunzzii Date: Mon, 9 Jun 2025 11:26:33 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20=EC=A7=80=EA=B0=81=20=EC=8B=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9E=A5=EC=97=90=EA=B2=8C=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd-dev.yml | 2 + .../domain/service}/AutoClockOutService.java | 4 +- .../scheduler}/AutoClockOutScheduler.java | 3 +- .../service}/AutoBillingService.java | 3 +- .../service}/SubscriptionBillingHandler.java | 7 ++- .../{ => external}/TossPaymentClient.java | 2 +- .../scheduler}/AutoBillingScheduler.java | 3 +- .../batch/clock_out/ScheduleRepository.java | 10 ---- .../AttendanceRepositoryImpl.java | 3 +- .../persistence}/BillingRepositoryImpl.java | 3 +- .../DeviceTokenRepositoryImpl.java | 22 +++++++ .../NotificationRepositoryImpl.java | 3 +- .../persistence/PayrollRepositoryImpl.java | 4 +- .../persistence/PayslipRepositoryImpl.java | 4 +- .../persistence}/ScheduleRepositoryImpl.java | 10 +++- .../SubscriptionOrderRepositoryImpl.java | 3 +- .../SubscriptionRepositoryImpl.java | 3 +- .../persistence}/UserRepositoryImpl.java | 3 +- .../repository}/AttendanceRepository.java | 2 +- .../repository}/BillingRepository.java | 2 +- .../repository/DeviceTokenRepository.java | 7 +++ .../repository}/NotificationRepository.java | 2 +- .../repository/PayrollRepository.java | 2 +- .../repository/PayslipRepository.java | 2 +- .../common/repository/ScheduleRepository.java | 12 ++++ .../SubscriptionOrderRepository.java | 2 +- .../repository}/SubscriptionRepository.java | 2 +- .../repository}/UserRepository.java | 2 +- .../domain/service/LateClockInService.java | 26 +++++++++ .../NotificationForLateClockInService.java | 58 +++++++++++++++++++ .../infra/scheduler/LateClockInScheduler.java | 17 ++++++ .../service}/NotificationHandler.java | 3 +- .../service}/NotificationService.java | 4 +- .../{ => external}/FcmInitializer.java | 2 +- .../{ => external}/FcmSender.java | 2 +- .../scheduler}/NotificationScheduler.java | 3 +- .../domain/service/AutoTransferService.java | 4 +- .../service/PayslipGenerationService.java | 2 +- batch/src/main/resources/application.yml | 5 +- .../notification/NotificationType.java | 2 +- .../schedule/ScheduleJpaRepository.java | 21 ++++++- .../ScheduleForLateClockInProjection.java | 10 ++++ 42 files changed, 239 insertions(+), 47 deletions(-) rename batch/src/main/java/com/mangoboss/batch/{clock_out => auto_clock_out/domain/service}/AutoClockOutService.java (89%) rename batch/src/main/java/com/mangoboss/batch/{clock_out => auto_clock_out/infra/scheduler}/AutoClockOutScheduler.java (75%) rename batch/src/main/java/com/mangoboss/batch/billing/{ => domain/service}/AutoBillingService.java (90%) rename batch/src/main/java/com/mangoboss/batch/billing/{ => domain/service}/SubscriptionBillingHandler.java (89%) rename batch/src/main/java/com/mangoboss/batch/billing/{ => external}/TossPaymentClient.java (98%) rename batch/src/main/java/com/mangoboss/batch/billing/{ => infra/scheduler}/AutoBillingScheduler.java (76%) delete mode 100644 batch/src/main/java/com/mangoboss/batch/clock_out/ScheduleRepository.java rename batch/src/main/java/com/mangoboss/batch/{clock_out => common/persistence}/AttendanceRepositoryImpl.java (82%) rename batch/src/main/java/com/mangoboss/batch/{billing => common/persistence}/BillingRepositoryImpl.java (82%) create mode 100644 batch/src/main/java/com/mangoboss/batch/common/persistence/DeviceTokenRepositoryImpl.java rename batch/src/main/java/com/mangoboss/batch/{notification => common/persistence}/NotificationRepositoryImpl.java (90%) rename batch/src/main/java/com/mangoboss/batch/{transfer/infra => common}/persistence/PayrollRepositoryImpl.java (89%) rename batch/src/main/java/com/mangoboss/batch/{transfer/infra => common}/persistence/PayslipRepositoryImpl.java (87%) rename batch/src/main/java/com/mangoboss/batch/{clock_out => common/persistence}/ScheduleRepositoryImpl.java (61%) rename batch/src/main/java/com/mangoboss/batch/{billing => common/persistence}/SubscriptionOrderRepositoryImpl.java (82%) rename batch/src/main/java/com/mangoboss/batch/{billing => common/persistence}/SubscriptionRepositoryImpl.java (88%) rename batch/src/main/java/com/mangoboss/batch/{billing => common/persistence}/UserRepositoryImpl.java (81%) rename batch/src/main/java/com/mangoboss/batch/{clock_out => common/repository}/AttendanceRepository.java (79%) rename batch/src/main/java/com/mangoboss/batch/{billing => common/repository}/BillingRepository.java (74%) create mode 100644 batch/src/main/java/com/mangoboss/batch/common/repository/DeviceTokenRepository.java rename batch/src/main/java/com/mangoboss/batch/{notification => common/repository}/NotificationRepository.java (91%) rename batch/src/main/java/com/mangoboss/batch/{transfer/domain => common}/repository/PayrollRepository.java (90%) rename batch/src/main/java/com/mangoboss/batch/{transfer/domain => common}/repository/PayslipRepository.java (87%) create mode 100644 batch/src/main/java/com/mangoboss/batch/common/repository/ScheduleRepository.java rename batch/src/main/java/com/mangoboss/batch/{billing => common/repository}/SubscriptionOrderRepository.java (78%) rename batch/src/main/java/com/mangoboss/batch/{billing => common/repository}/SubscriptionRepository.java (88%) rename batch/src/main/java/com/mangoboss/batch/{billing => common/repository}/UserRepository.java (71%) create mode 100644 batch/src/main/java/com/mangoboss/batch/late_clock_in/domain/service/LateClockInService.java create mode 100644 batch/src/main/java/com/mangoboss/batch/late_clock_in/domain/service/NotificationForLateClockInService.java create mode 100644 batch/src/main/java/com/mangoboss/batch/late_clock_in/infra/scheduler/LateClockInScheduler.java rename batch/src/main/java/com/mangoboss/batch/notification/{ => domain/service}/NotificationHandler.java (88%) rename batch/src/main/java/com/mangoboss/batch/notification/{ => domain/service}/NotificationService.java (87%) rename batch/src/main/java/com/mangoboss/batch/notification/{ => external}/FcmInitializer.java (95%) rename batch/src/main/java/com/mangoboss/batch/notification/{ => external}/FcmSender.java (98%) rename batch/src/main/java/com/mangoboss/batch/notification/{ => infra/scheduler}/NotificationScheduler.java (75%) create mode 100644 storage/src/main/java/com/mangoboss/storage/schedule/projection/ScheduleForLateClockInProjection.java diff --git a/.github/workflows/cd-dev.yml b/.github/workflows/cd-dev.yml index 2d9956ea..513479ff 100644 --- a/.github/workflows/cd-dev.yml +++ b/.github/workflows/cd-dev.yml @@ -235,6 +235,8 @@ jobs: echo "CRON_PAYSLIP=${{ secrets.CRON_PAYSLIP }}" >> .env echo "CRON_NOTIFICATION=${{ secrets.CRON_NOTIFICATION }}" >> .env echo "CRON_BILLING=${{ secrets.CRON_BILLING }}" >> .env + echo "CRON_CLOCK_IN=${{ secrets.CRON_CLOCK_IN }}" >> .env + echo "FRONTEND_URL=${{ secrets.FRONTEND_URL }}" >> .env echo "PAYROLL_BATCH_SIZE=${{ secrets.PAYROLL_BATCH_SIZE }}" >> .env echo "PAYSLIP_BATCH_SIZE=${{ secrets.PAYSLIP_BATCH_SIZE }}" >> .env echo "NOTIFICATION_BATCH_SIZE=${{ secrets.NOTIFICATION_BATCH_SIZE }}" >> .env diff --git a/batch/src/main/java/com/mangoboss/batch/clock_out/AutoClockOutService.java b/batch/src/main/java/com/mangoboss/batch/auto_clock_out/domain/service/AutoClockOutService.java similarity index 89% rename from batch/src/main/java/com/mangoboss/batch/clock_out/AutoClockOutService.java rename to batch/src/main/java/com/mangoboss/batch/auto_clock_out/domain/service/AutoClockOutService.java index bc6c92c5..48f0632e 100644 --- a/batch/src/main/java/com/mangoboss/batch/clock_out/AutoClockOutService.java +++ b/batch/src/main/java/com/mangoboss/batch/auto_clock_out/domain/service/AutoClockOutService.java @@ -1,5 +1,7 @@ -package com.mangoboss.batch.clock_out; +package com.mangoboss.batch.auto_clock_out.domain.service; +import com.mangoboss.batch.common.repository.AttendanceRepository; +import com.mangoboss.batch.common.repository.ScheduleRepository; import com.mangoboss.storage.attendance.AttendanceEntity; import com.mangoboss.storage.attendance.ClockInStatus; import com.mangoboss.storage.attendance.ClockOutStatus; diff --git a/batch/src/main/java/com/mangoboss/batch/clock_out/AutoClockOutScheduler.java b/batch/src/main/java/com/mangoboss/batch/auto_clock_out/infra/scheduler/AutoClockOutScheduler.java similarity index 75% rename from batch/src/main/java/com/mangoboss/batch/clock_out/AutoClockOutScheduler.java rename to batch/src/main/java/com/mangoboss/batch/auto_clock_out/infra/scheduler/AutoClockOutScheduler.java index 2e11ec4d..238913f6 100644 --- a/batch/src/main/java/com/mangoboss/batch/clock_out/AutoClockOutScheduler.java +++ b/batch/src/main/java/com/mangoboss/batch/auto_clock_out/infra/scheduler/AutoClockOutScheduler.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.clock_out; +package com.mangoboss.batch.auto_clock_out.infra.scheduler; +import com.mangoboss.batch.auto_clock_out.domain.service.AutoClockOutService; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; diff --git a/batch/src/main/java/com/mangoboss/batch/billing/AutoBillingService.java b/batch/src/main/java/com/mangoboss/batch/billing/domain/service/AutoBillingService.java similarity index 90% rename from batch/src/main/java/com/mangoboss/batch/billing/AutoBillingService.java rename to batch/src/main/java/com/mangoboss/batch/billing/domain/service/AutoBillingService.java index 31436fce..1ae97c36 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/AutoBillingService.java +++ b/batch/src/main/java/com/mangoboss/batch/billing/domain/service/AutoBillingService.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.billing.domain.service; +import com.mangoboss.batch.common.repository.SubscriptionRepository; import com.mangoboss.storage.subscription.SubscriptionEntity; import lombok.RequiredArgsConstructor; diff --git a/batch/src/main/java/com/mangoboss/batch/billing/SubscriptionBillingHandler.java b/batch/src/main/java/com/mangoboss/batch/billing/domain/service/SubscriptionBillingHandler.java similarity index 89% rename from batch/src/main/java/com/mangoboss/batch/billing/SubscriptionBillingHandler.java rename to batch/src/main/java/com/mangoboss/batch/billing/domain/service/SubscriptionBillingHandler.java index f7fdc96d..b72b3b3a 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/SubscriptionBillingHandler.java +++ b/batch/src/main/java/com/mangoboss/batch/billing/domain/service/SubscriptionBillingHandler.java @@ -1,5 +1,10 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.billing.domain.service; +import com.mangoboss.batch.common.repository.BillingRepository; +import com.mangoboss.batch.common.repository.SubscriptionOrderRepository; +import com.mangoboss.batch.common.repository.SubscriptionRepository; +import com.mangoboss.batch.common.repository.UserRepository; +import com.mangoboss.batch.billing.external.TossPaymentClient; import com.mangoboss.storage.billing.BillingEntity; import com.mangoboss.storage.subscription.SubscriptionEntity; import com.mangoboss.storage.subscription.SubscriptionOrderEntity; diff --git a/batch/src/main/java/com/mangoboss/batch/billing/TossPaymentClient.java b/batch/src/main/java/com/mangoboss/batch/billing/external/TossPaymentClient.java similarity index 98% rename from batch/src/main/java/com/mangoboss/batch/billing/TossPaymentClient.java rename to batch/src/main/java/com/mangoboss/batch/billing/external/TossPaymentClient.java index e2a27589..7f2e8f19 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/TossPaymentClient.java +++ b/batch/src/main/java/com/mangoboss/batch/billing/external/TossPaymentClient.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.billing.external; import com.fasterxml.jackson.databind.ObjectMapper; import com.mangoboss.batch.common.exception.CustomErrorInfo; diff --git a/batch/src/main/java/com/mangoboss/batch/billing/AutoBillingScheduler.java b/batch/src/main/java/com/mangoboss/batch/billing/infra/scheduler/AutoBillingScheduler.java similarity index 76% rename from batch/src/main/java/com/mangoboss/batch/billing/AutoBillingScheduler.java rename to batch/src/main/java/com/mangoboss/batch/billing/infra/scheduler/AutoBillingScheduler.java index 978bc5c6..7ce7e6b3 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/AutoBillingScheduler.java +++ b/batch/src/main/java/com/mangoboss/batch/billing/infra/scheduler/AutoBillingScheduler.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.billing.infra.scheduler; +import com.mangoboss.batch.billing.domain.service.AutoBillingService; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; diff --git a/batch/src/main/java/com/mangoboss/batch/clock_out/ScheduleRepository.java b/batch/src/main/java/com/mangoboss/batch/clock_out/ScheduleRepository.java deleted file mode 100644 index 13beff1b..00000000 --- a/batch/src/main/java/com/mangoboss/batch/clock_out/ScheduleRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mangoboss.batch.clock_out; - -import com.mangoboss.storage.schedule.ScheduleEntity; - -import java.util.List; - -public interface ScheduleRepository { - List findAllSchedulesWithoutClockOut(); - -} diff --git a/batch/src/main/java/com/mangoboss/batch/clock_out/AttendanceRepositoryImpl.java b/batch/src/main/java/com/mangoboss/batch/common/persistence/AttendanceRepositoryImpl.java similarity index 82% rename from batch/src/main/java/com/mangoboss/batch/clock_out/AttendanceRepositoryImpl.java rename to batch/src/main/java/com/mangoboss/batch/common/persistence/AttendanceRepositoryImpl.java index ef3ce10d..ba07bd6c 100644 --- a/batch/src/main/java/com/mangoboss/batch/clock_out/AttendanceRepositoryImpl.java +++ b/batch/src/main/java/com/mangoboss/batch/common/persistence/AttendanceRepositoryImpl.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.clock_out; +package com.mangoboss.batch.common.persistence; +import com.mangoboss.batch.common.repository.AttendanceRepository; import com.mangoboss.storage.attendance.AttendanceEntity; import com.mangoboss.storage.attendance.AttendanceJpaRepository; import lombok.RequiredArgsConstructor; diff --git a/batch/src/main/java/com/mangoboss/batch/billing/BillingRepositoryImpl.java b/batch/src/main/java/com/mangoboss/batch/common/persistence/BillingRepositoryImpl.java similarity index 82% rename from batch/src/main/java/com/mangoboss/batch/billing/BillingRepositoryImpl.java rename to batch/src/main/java/com/mangoboss/batch/common/persistence/BillingRepositoryImpl.java index bdfeb7a3..b6925db3 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/BillingRepositoryImpl.java +++ b/batch/src/main/java/com/mangoboss/batch/common/persistence/BillingRepositoryImpl.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.common.persistence; +import com.mangoboss.batch.common.repository.BillingRepository; import com.mangoboss.storage.billing.BillingEntity; import com.mangoboss.storage.billing.BillingJpaRepository; import lombok.RequiredArgsConstructor; diff --git a/batch/src/main/java/com/mangoboss/batch/common/persistence/DeviceTokenRepositoryImpl.java b/batch/src/main/java/com/mangoboss/batch/common/persistence/DeviceTokenRepositoryImpl.java new file mode 100644 index 00000000..b0a79ea9 --- /dev/null +++ b/batch/src/main/java/com/mangoboss/batch/common/persistence/DeviceTokenRepositoryImpl.java @@ -0,0 +1,22 @@ +package com.mangoboss.batch.common.persistence; + +import com.mangoboss.batch.common.repository.DeviceTokenRepository; +import com.mangoboss.storage.notification.DeviceTokenEntity; +import com.mangoboss.storage.notification.DeviceTokenJpaRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@RequiredArgsConstructor +public class DeviceTokenRepositoryImpl implements DeviceTokenRepository { + private final DeviceTokenJpaRepository deviceTokenJpaRepository; + + @Override + public List findActiveTokensByUserId(final Long userId) { + return deviceTokenJpaRepository.findByUserIdAndIsDeletedFalse(userId).stream() + .map(DeviceTokenEntity::getTokenValue) + .toList(); + } +} diff --git a/batch/src/main/java/com/mangoboss/batch/notification/NotificationRepositoryImpl.java b/batch/src/main/java/com/mangoboss/batch/common/persistence/NotificationRepositoryImpl.java similarity index 90% rename from batch/src/main/java/com/mangoboss/batch/notification/NotificationRepositoryImpl.java rename to batch/src/main/java/com/mangoboss/batch/common/persistence/NotificationRepositoryImpl.java index 311166fb..f16efae2 100644 --- a/batch/src/main/java/com/mangoboss/batch/notification/NotificationRepositoryImpl.java +++ b/batch/src/main/java/com/mangoboss/batch/common/persistence/NotificationRepositoryImpl.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.notification; +package com.mangoboss.batch.common.persistence; +import com.mangoboss.batch.common.repository.NotificationRepository; import com.mangoboss.storage.notification.NotificationEntity; import com.mangoboss.storage.notification.NotificationJpaRepository; import com.mangoboss.storage.notification.SendStatus; diff --git a/batch/src/main/java/com/mangoboss/batch/transfer/infra/persistence/PayrollRepositoryImpl.java b/batch/src/main/java/com/mangoboss/batch/common/persistence/PayrollRepositoryImpl.java similarity index 89% rename from batch/src/main/java/com/mangoboss/batch/transfer/infra/persistence/PayrollRepositoryImpl.java rename to batch/src/main/java/com/mangoboss/batch/common/persistence/PayrollRepositoryImpl.java index 05ff6b97..d93c9b9a 100644 --- a/batch/src/main/java/com/mangoboss/batch/transfer/infra/persistence/PayrollRepositoryImpl.java +++ b/batch/src/main/java/com/mangoboss/batch/common/persistence/PayrollRepositoryImpl.java @@ -1,6 +1,6 @@ -package com.mangoboss.batch.transfer.infra.persistence; +package com.mangoboss.batch.common.persistence; -import com.mangoboss.batch.transfer.domain.repository.PayrollRepository; +import com.mangoboss.batch.common.repository.PayrollRepository; import com.mangoboss.storage.payroll.PayrollEntity; import com.mangoboss.storage.payroll.PayrollJpaRepository; import com.mangoboss.storage.payroll.TransferState; diff --git a/batch/src/main/java/com/mangoboss/batch/transfer/infra/persistence/PayslipRepositoryImpl.java b/batch/src/main/java/com/mangoboss/batch/common/persistence/PayslipRepositoryImpl.java similarity index 87% rename from batch/src/main/java/com/mangoboss/batch/transfer/infra/persistence/PayslipRepositoryImpl.java rename to batch/src/main/java/com/mangoboss/batch/common/persistence/PayslipRepositoryImpl.java index 767cc404..220174b8 100644 --- a/batch/src/main/java/com/mangoboss/batch/transfer/infra/persistence/PayslipRepositoryImpl.java +++ b/batch/src/main/java/com/mangoboss/batch/common/persistence/PayslipRepositoryImpl.java @@ -1,6 +1,6 @@ -package com.mangoboss.batch.transfer.infra.persistence; +package com.mangoboss.batch.common.persistence; -import com.mangoboss.batch.transfer.domain.repository.PayslipRepository; +import com.mangoboss.batch.common.repository.PayslipRepository; import com.mangoboss.storage.payroll.PayslipEntity; import com.mangoboss.storage.payroll.PayslipJpaRepository; import com.mangoboss.storage.payroll.PayslipState; diff --git a/batch/src/main/java/com/mangoboss/batch/clock_out/ScheduleRepositoryImpl.java b/batch/src/main/java/com/mangoboss/batch/common/persistence/ScheduleRepositoryImpl.java similarity index 61% rename from batch/src/main/java/com/mangoboss/batch/clock_out/ScheduleRepositoryImpl.java rename to batch/src/main/java/com/mangoboss/batch/common/persistence/ScheduleRepositoryImpl.java index d9bbf8c5..3f2405ec 100644 --- a/batch/src/main/java/com/mangoboss/batch/clock_out/ScheduleRepositoryImpl.java +++ b/batch/src/main/java/com/mangoboss/batch/common/persistence/ScheduleRepositoryImpl.java @@ -1,7 +1,9 @@ -package com.mangoboss.batch.clock_out; +package com.mangoboss.batch.common.persistence; +import com.mangoboss.batch.common.repository.ScheduleRepository; import com.mangoboss.storage.schedule.ScheduleEntity; import com.mangoboss.storage.schedule.ScheduleJpaRepository; +import com.mangoboss.storage.schedule.projection.ScheduleForLateClockInProjection; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; @@ -20,4 +22,10 @@ public List findAllSchedulesWithoutClockOut() { LocalDateTime oneHourAgo = LocalDateTime.now(clock).minusHours(1); return scheduleJpaRepository.findAllSchedulesWithoutClockOut(oneHourAgo); } + + @Override + public List findAllSchedulesWithoutClockIn() { + LocalDateTime temMinuteAgo = LocalDateTime.now(clock).minusMinutes(10); + return scheduleJpaRepository.findLateSchedulesWithoutAlarm(temMinuteAgo); + } } diff --git a/batch/src/main/java/com/mangoboss/batch/billing/SubscriptionOrderRepositoryImpl.java b/batch/src/main/java/com/mangoboss/batch/common/persistence/SubscriptionOrderRepositoryImpl.java similarity index 82% rename from batch/src/main/java/com/mangoboss/batch/billing/SubscriptionOrderRepositoryImpl.java rename to batch/src/main/java/com/mangoboss/batch/common/persistence/SubscriptionOrderRepositoryImpl.java index 5f8ebd17..dcaf9a0d 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/SubscriptionOrderRepositoryImpl.java +++ b/batch/src/main/java/com/mangoboss/batch/common/persistence/SubscriptionOrderRepositoryImpl.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.common.persistence; +import com.mangoboss.batch.common.repository.SubscriptionOrderRepository; import com.mangoboss.storage.subscription.SubscriptionOrderEntity; import com.mangoboss.storage.subscription.SubscriptionOrderJpaRepository; import lombok.RequiredArgsConstructor; diff --git a/batch/src/main/java/com/mangoboss/batch/billing/SubscriptionRepositoryImpl.java b/batch/src/main/java/com/mangoboss/batch/common/persistence/SubscriptionRepositoryImpl.java similarity index 88% rename from batch/src/main/java/com/mangoboss/batch/billing/SubscriptionRepositoryImpl.java rename to batch/src/main/java/com/mangoboss/batch/common/persistence/SubscriptionRepositoryImpl.java index f20600ad..9d5603a9 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/SubscriptionRepositoryImpl.java +++ b/batch/src/main/java/com/mangoboss/batch/common/persistence/SubscriptionRepositoryImpl.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.common.persistence; +import com.mangoboss.batch.common.repository.SubscriptionRepository; import com.mangoboss.storage.subscription.SubscriptionEntity; import com.mangoboss.storage.subscription.SubscriptionJpaRepository; import lombok.RequiredArgsConstructor; diff --git a/batch/src/main/java/com/mangoboss/batch/billing/UserRepositoryImpl.java b/batch/src/main/java/com/mangoboss/batch/common/persistence/UserRepositoryImpl.java similarity index 81% rename from batch/src/main/java/com/mangoboss/batch/billing/UserRepositoryImpl.java rename to batch/src/main/java/com/mangoboss/batch/common/persistence/UserRepositoryImpl.java index c9fc6868..9bf46698 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/UserRepositoryImpl.java +++ b/batch/src/main/java/com/mangoboss/batch/common/persistence/UserRepositoryImpl.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.common.persistence; +import com.mangoboss.batch.common.repository.UserRepository; import com.mangoboss.storage.user.UserEntity; import com.mangoboss.storage.user.UserJpaRepository; import lombok.RequiredArgsConstructor; diff --git a/batch/src/main/java/com/mangoboss/batch/clock_out/AttendanceRepository.java b/batch/src/main/java/com/mangoboss/batch/common/repository/AttendanceRepository.java similarity index 79% rename from batch/src/main/java/com/mangoboss/batch/clock_out/AttendanceRepository.java rename to batch/src/main/java/com/mangoboss/batch/common/repository/AttendanceRepository.java index 95d2ce34..624ef007 100644 --- a/batch/src/main/java/com/mangoboss/batch/clock_out/AttendanceRepository.java +++ b/batch/src/main/java/com/mangoboss/batch/common/repository/AttendanceRepository.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.clock_out; +package com.mangoboss.batch.common.repository; import com.mangoboss.storage.attendance.AttendanceEntity; diff --git a/batch/src/main/java/com/mangoboss/batch/billing/BillingRepository.java b/batch/src/main/java/com/mangoboss/batch/common/repository/BillingRepository.java similarity index 74% rename from batch/src/main/java/com/mangoboss/batch/billing/BillingRepository.java rename to batch/src/main/java/com/mangoboss/batch/common/repository/BillingRepository.java index 16d9892a..d11cd758 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/BillingRepository.java +++ b/batch/src/main/java/com/mangoboss/batch/common/repository/BillingRepository.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.common.repository; import com.mangoboss.storage.billing.BillingEntity; diff --git a/batch/src/main/java/com/mangoboss/batch/common/repository/DeviceTokenRepository.java b/batch/src/main/java/com/mangoboss/batch/common/repository/DeviceTokenRepository.java new file mode 100644 index 00000000..1040d3d1 --- /dev/null +++ b/batch/src/main/java/com/mangoboss/batch/common/repository/DeviceTokenRepository.java @@ -0,0 +1,7 @@ +package com.mangoboss.batch.common.repository; + +import java.util.List; + +public interface DeviceTokenRepository { + List findActiveTokensByUserId(Long userId); +} diff --git a/batch/src/main/java/com/mangoboss/batch/notification/NotificationRepository.java b/batch/src/main/java/com/mangoboss/batch/common/repository/NotificationRepository.java similarity index 91% rename from batch/src/main/java/com/mangoboss/batch/notification/NotificationRepository.java rename to batch/src/main/java/com/mangoboss/batch/common/repository/NotificationRepository.java index 5f03eba0..e068dc17 100644 --- a/batch/src/main/java/com/mangoboss/batch/notification/NotificationRepository.java +++ b/batch/src/main/java/com/mangoboss/batch/common/repository/NotificationRepository.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.notification; +package com.mangoboss.batch.common.repository; import com.mangoboss.storage.notification.NotificationEntity; import com.mangoboss.storage.notification.SendStatus; diff --git a/batch/src/main/java/com/mangoboss/batch/transfer/domain/repository/PayrollRepository.java b/batch/src/main/java/com/mangoboss/batch/common/repository/PayrollRepository.java similarity index 90% rename from batch/src/main/java/com/mangoboss/batch/transfer/domain/repository/PayrollRepository.java rename to batch/src/main/java/com/mangoboss/batch/common/repository/PayrollRepository.java index a12afdc4..785381ce 100644 --- a/batch/src/main/java/com/mangoboss/batch/transfer/domain/repository/PayrollRepository.java +++ b/batch/src/main/java/com/mangoboss/batch/common/repository/PayrollRepository.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.transfer.domain.repository; +package com.mangoboss.batch.common.repository; import com.mangoboss.storage.payroll.PayrollEntity; import com.mangoboss.storage.payroll.TransferState; diff --git a/batch/src/main/java/com/mangoboss/batch/transfer/domain/repository/PayslipRepository.java b/batch/src/main/java/com/mangoboss/batch/common/repository/PayslipRepository.java similarity index 87% rename from batch/src/main/java/com/mangoboss/batch/transfer/domain/repository/PayslipRepository.java rename to batch/src/main/java/com/mangoboss/batch/common/repository/PayslipRepository.java index 74399991..3772339f 100644 --- a/batch/src/main/java/com/mangoboss/batch/transfer/domain/repository/PayslipRepository.java +++ b/batch/src/main/java/com/mangoboss/batch/common/repository/PayslipRepository.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.transfer.domain.repository; +package com.mangoboss.batch.common.repository; import com.mangoboss.storage.payroll.PayslipEntity; import com.mangoboss.storage.payroll.PayslipState; diff --git a/batch/src/main/java/com/mangoboss/batch/common/repository/ScheduleRepository.java b/batch/src/main/java/com/mangoboss/batch/common/repository/ScheduleRepository.java new file mode 100644 index 00000000..c5cc8817 --- /dev/null +++ b/batch/src/main/java/com/mangoboss/batch/common/repository/ScheduleRepository.java @@ -0,0 +1,12 @@ +package com.mangoboss.batch.common.repository; + +import com.mangoboss.storage.schedule.ScheduleEntity; +import com.mangoboss.storage.schedule.projection.ScheduleForLateClockInProjection; + +import java.util.List; + +public interface ScheduleRepository { + List findAllSchedulesWithoutClockOut(); + + List findAllSchedulesWithoutClockIn(); +} diff --git a/batch/src/main/java/com/mangoboss/batch/billing/SubscriptionOrderRepository.java b/batch/src/main/java/com/mangoboss/batch/common/repository/SubscriptionOrderRepository.java similarity index 78% rename from batch/src/main/java/com/mangoboss/batch/billing/SubscriptionOrderRepository.java rename to batch/src/main/java/com/mangoboss/batch/common/repository/SubscriptionOrderRepository.java index 50308327..cb235077 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/SubscriptionOrderRepository.java +++ b/batch/src/main/java/com/mangoboss/batch/common/repository/SubscriptionOrderRepository.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.common.repository; import com.mangoboss.storage.subscription.SubscriptionOrderEntity; diff --git a/batch/src/main/java/com/mangoboss/batch/billing/SubscriptionRepository.java b/batch/src/main/java/com/mangoboss/batch/common/repository/SubscriptionRepository.java similarity index 88% rename from batch/src/main/java/com/mangoboss/batch/billing/SubscriptionRepository.java rename to batch/src/main/java/com/mangoboss/batch/common/repository/SubscriptionRepository.java index 1fdcc111..c4ac611c 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/SubscriptionRepository.java +++ b/batch/src/main/java/com/mangoboss/batch/common/repository/SubscriptionRepository.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.common.repository; import com.mangoboss.storage.subscription.SubscriptionEntity; import org.springframework.data.domain.Pageable; diff --git a/batch/src/main/java/com/mangoboss/batch/billing/UserRepository.java b/batch/src/main/java/com/mangoboss/batch/common/repository/UserRepository.java similarity index 71% rename from batch/src/main/java/com/mangoboss/batch/billing/UserRepository.java rename to batch/src/main/java/com/mangoboss/batch/common/repository/UserRepository.java index e4e2fac7..ab184e91 100644 --- a/batch/src/main/java/com/mangoboss/batch/billing/UserRepository.java +++ b/batch/src/main/java/com/mangoboss/batch/common/repository/UserRepository.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.billing; +package com.mangoboss.batch.common.repository; import com.mangoboss.storage.user.UserEntity; diff --git a/batch/src/main/java/com/mangoboss/batch/late_clock_in/domain/service/LateClockInService.java b/batch/src/main/java/com/mangoboss/batch/late_clock_in/domain/service/LateClockInService.java new file mode 100644 index 00000000..50046756 --- /dev/null +++ b/batch/src/main/java/com/mangoboss/batch/late_clock_in/domain/service/LateClockInService.java @@ -0,0 +1,26 @@ +package com.mangoboss.batch.late_clock_in.domain.service; + +import com.mangoboss.batch.common.repository.ScheduleRepository; +import com.mangoboss.storage.schedule.projection.ScheduleForLateClockInProjection; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class LateClockInService { + private final ScheduleRepository scheduleRepository; + private final NotificationForLateClockInService notificationService; + + @Transactional + public void notifyLateClockIn(){ + List lateSchedules = scheduleRepository.findAllSchedulesWithoutClockIn(); + if (lateSchedules.isEmpty()) { + return; + } + notificationService.saveNotifications(lateSchedules); + } + +} diff --git a/batch/src/main/java/com/mangoboss/batch/late_clock_in/domain/service/NotificationForLateClockInService.java b/batch/src/main/java/com/mangoboss/batch/late_clock_in/domain/service/NotificationForLateClockInService.java new file mode 100644 index 00000000..0bc3cf9b --- /dev/null +++ b/batch/src/main/java/com/mangoboss/batch/late_clock_in/domain/service/NotificationForLateClockInService.java @@ -0,0 +1,58 @@ +package com.mangoboss.batch.late_clock_in.domain.service; + +import com.mangoboss.batch.common.repository.DeviceTokenRepository; +import com.mangoboss.batch.common.repository.NotificationRepository; +import com.mangoboss.storage.notification.NotificationEntity; +import com.mangoboss.storage.notification.NotificationType; +import com.mangoboss.storage.schedule.projection.ScheduleForLateClockInProjection; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class NotificationForLateClockInService { + private final NotificationRepository notificationRepository; + private final DeviceTokenRepository deviceTokenRepository; + + @Value("${frontend-url}") + private String frontendUrl; + + private List generateNotification(final Long userId, final Long storeId, final Long scheduleId, final String title, + final String content, final NotificationType type, final String path) { + String clickUrl = frontendUrl + path; + List tokens = deviceTokenRepository.findActiveTokensByUserId(userId); + return tokens.stream() + .map(token -> NotificationEntity.createWithMetaId(userId, storeId, title, content, null, clickUrl, type, token, scheduleId)) + .toList(); + } + + private List generateContractSignNotification(final Long userId, final Long storeId, final String staffName, final Long scheduleId) { + String content = String.format("%s님이 출근 시간으로부터 10분이 지나도 출근하지 않았어요.", staffName); + return generateNotification( + userId, + storeId, + scheduleId, + "지각 알림", + content, + NotificationType.SCHEDULE, + "/boss/schedule" + ); + } + + @Transactional + public void saveNotifications(final List scheduleProjections) { + List notifications = scheduleProjections.stream() + .flatMap(schedule -> generateContractSignNotification( + schedule.getBossId(), + schedule.getStoreId(), + schedule.getStaffName(), + schedule.getSchedule().getId() + ).stream()) + .toList(); + notificationRepository.saveAll(notifications); + } +} diff --git a/batch/src/main/java/com/mangoboss/batch/late_clock_in/infra/scheduler/LateClockInScheduler.java b/batch/src/main/java/com/mangoboss/batch/late_clock_in/infra/scheduler/LateClockInScheduler.java new file mode 100644 index 00000000..c177ebfa --- /dev/null +++ b/batch/src/main/java/com/mangoboss/batch/late_clock_in/infra/scheduler/LateClockInScheduler.java @@ -0,0 +1,17 @@ +package com.mangoboss.batch.late_clock_in.infra.scheduler; + +import com.mangoboss.batch.late_clock_in.domain.service.LateClockInService; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class LateClockInScheduler { + private final LateClockInService lateClockInNotificationService; + + @Scheduled(cron = "${cron.clock-in}") + public void runLateClockInNotification() { + lateClockInNotificationService.notifyLateClockIn(); + } +} diff --git a/batch/src/main/java/com/mangoboss/batch/notification/NotificationHandler.java b/batch/src/main/java/com/mangoboss/batch/notification/domain/service/NotificationHandler.java similarity index 88% rename from batch/src/main/java/com/mangoboss/batch/notification/NotificationHandler.java rename to batch/src/main/java/com/mangoboss/batch/notification/domain/service/NotificationHandler.java index 8937a13e..e14edddf 100644 --- a/batch/src/main/java/com/mangoboss/batch/notification/NotificationHandler.java +++ b/batch/src/main/java/com/mangoboss/batch/notification/domain/service/NotificationHandler.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.notification; +package com.mangoboss.batch.notification.domain.service; +import com.mangoboss.batch.common.repository.NotificationRepository; import com.mangoboss.storage.notification.NotificationEntity; import com.mangoboss.storage.notification.SendStatus; import lombok.RequiredArgsConstructor; diff --git a/batch/src/main/java/com/mangoboss/batch/notification/NotificationService.java b/batch/src/main/java/com/mangoboss/batch/notification/domain/service/NotificationService.java similarity index 87% rename from batch/src/main/java/com/mangoboss/batch/notification/NotificationService.java rename to batch/src/main/java/com/mangoboss/batch/notification/domain/service/NotificationService.java index e34df836..8c134609 100644 --- a/batch/src/main/java/com/mangoboss/batch/notification/NotificationService.java +++ b/batch/src/main/java/com/mangoboss/batch/notification/domain/service/NotificationService.java @@ -1,5 +1,7 @@ -package com.mangoboss.batch.notification; +package com.mangoboss.batch.notification.domain.service; +import com.mangoboss.batch.common.repository.NotificationRepository; +import com.mangoboss.batch.notification.external.FcmSender; import com.mangoboss.storage.notification.NotificationEntity; import com.mangoboss.storage.notification.SendStatus; import lombok.RequiredArgsConstructor; diff --git a/batch/src/main/java/com/mangoboss/batch/notification/FcmInitializer.java b/batch/src/main/java/com/mangoboss/batch/notification/external/FcmInitializer.java similarity index 95% rename from batch/src/main/java/com/mangoboss/batch/notification/FcmInitializer.java rename to batch/src/main/java/com/mangoboss/batch/notification/external/FcmInitializer.java index db5f1746..8f484257 100644 --- a/batch/src/main/java/com/mangoboss/batch/notification/FcmInitializer.java +++ b/batch/src/main/java/com/mangoboss/batch/notification/external/FcmInitializer.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.notification; +package com.mangoboss.batch.notification.external; import java.io.IOException; import java.io.InputStream; diff --git a/batch/src/main/java/com/mangoboss/batch/notification/FcmSender.java b/batch/src/main/java/com/mangoboss/batch/notification/external/FcmSender.java similarity index 98% rename from batch/src/main/java/com/mangoboss/batch/notification/FcmSender.java rename to batch/src/main/java/com/mangoboss/batch/notification/external/FcmSender.java index 6b1eef96..4f0dab6a 100644 --- a/batch/src/main/java/com/mangoboss/batch/notification/FcmSender.java +++ b/batch/src/main/java/com/mangoboss/batch/notification/external/FcmSender.java @@ -1,4 +1,4 @@ -package com.mangoboss.batch.notification; +package com.mangoboss.batch.notification.external; import com.google.api.core.ApiFuture; import com.google.firebase.messaging.BatchResponse; diff --git a/batch/src/main/java/com/mangoboss/batch/notification/NotificationScheduler.java b/batch/src/main/java/com/mangoboss/batch/notification/infra/scheduler/NotificationScheduler.java similarity index 75% rename from batch/src/main/java/com/mangoboss/batch/notification/NotificationScheduler.java rename to batch/src/main/java/com/mangoboss/batch/notification/infra/scheduler/NotificationScheduler.java index 394825ea..78bc7dc9 100644 --- a/batch/src/main/java/com/mangoboss/batch/notification/NotificationScheduler.java +++ b/batch/src/main/java/com/mangoboss/batch/notification/infra/scheduler/NotificationScheduler.java @@ -1,5 +1,6 @@ -package com.mangoboss.batch.notification; +package com.mangoboss.batch.notification.infra.scheduler; +import com.mangoboss.batch.notification.domain.service.NotificationService; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; diff --git a/batch/src/main/java/com/mangoboss/batch/transfer/domain/service/AutoTransferService.java b/batch/src/main/java/com/mangoboss/batch/transfer/domain/service/AutoTransferService.java index 8215c4e2..93531f08 100644 --- a/batch/src/main/java/com/mangoboss/batch/transfer/domain/service/AutoTransferService.java +++ b/batch/src/main/java/com/mangoboss/batch/transfer/domain/service/AutoTransferService.java @@ -1,7 +1,7 @@ package com.mangoboss.batch.transfer.domain.service; -import com.mangoboss.batch.transfer.domain.repository.PayrollRepository; -import com.mangoboss.batch.transfer.domain.repository.PayslipRepository; +import com.mangoboss.batch.common.repository.PayrollRepository; +import com.mangoboss.batch.common.repository.PayslipRepository; import com.mangoboss.storage.payroll.PayrollEntity; import com.mangoboss.storage.payroll.PayslipEntity; import com.mangoboss.storage.payroll.TransferState; diff --git a/batch/src/main/java/com/mangoboss/batch/transfer/domain/service/PayslipGenerationService.java b/batch/src/main/java/com/mangoboss/batch/transfer/domain/service/PayslipGenerationService.java index 5e47fcd7..470ea661 100644 --- a/batch/src/main/java/com/mangoboss/batch/transfer/domain/service/PayslipGenerationService.java +++ b/batch/src/main/java/com/mangoboss/batch/transfer/domain/service/PayslipGenerationService.java @@ -1,7 +1,7 @@ package com.mangoboss.batch.transfer.domain.service; import com.mangoboss.batch.common.exception.CustomErrorInfo; -import com.mangoboss.batch.transfer.domain.repository.PayslipRepository; +import com.mangoboss.batch.common.repository.PayslipRepository; import com.mangoboss.storage.payroll.PayrollEntity; import com.mangoboss.storage.payroll.PayslipEntity; import com.mangoboss.storage.payroll.PayslipState; diff --git a/batch/src/main/resources/application.yml b/batch/src/main/resources/application.yml index e94167e9..83a5c8f9 100644 --- a/batch/src/main/resources/application.yml +++ b/batch/src/main/resources/application.yml @@ -42,6 +42,7 @@ cron: payslip: ${CRON_PAYSLIP} notification: ${CRON_NOTIFICATION} billing: ${CRON_BILLING} + clock-in : ${CRON_CLOCK_IN} transfer: max-retry: ${MAX_RETRY} @@ -71,4 +72,6 @@ firebase: notification: max-retry: ${MAX_RETRY:3} - notification-batch-size: ${NOTIFICATION_BATCH_SIZE:400} \ No newline at end of file + notification-batch-size: ${NOTIFICATION_BATCH_SIZE:400} + +frontend-url: ${FRONTEND_URL} \ No newline at end of file diff --git a/storage/src/main/java/com/mangoboss/storage/notification/NotificationType.java b/storage/src/main/java/com/mangoboss/storage/notification/NotificationType.java index 5184a5ec..ca6fe1ba 100644 --- a/storage/src/main/java/com/mangoboss/storage/notification/NotificationType.java +++ b/storage/src/main/java/com/mangoboss/storage/notification/NotificationType.java @@ -1,5 +1,5 @@ package com.mangoboss.storage.notification; public enum NotificationType { - CONTRACT, SUBSTITUTE, + CONTRACT, SUBSTITUTE, SCHEDULE } \ No newline at end of file diff --git a/storage/src/main/java/com/mangoboss/storage/schedule/ScheduleJpaRepository.java b/storage/src/main/java/com/mangoboss/storage/schedule/ScheduleJpaRepository.java index 7ffe7471..5c04fc90 100644 --- a/storage/src/main/java/com/mangoboss/storage/schedule/ScheduleJpaRepository.java +++ b/storage/src/main/java/com/mangoboss/storage/schedule/ScheduleJpaRepository.java @@ -1,5 +1,6 @@ package com.mangoboss.storage.schedule; +import com.mangoboss.storage.schedule.projection.ScheduleForLateClockInProjection; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -27,9 +28,9 @@ public interface ScheduleJpaRepository extends JpaRepository findAllSchedulesWithoutClockOut(LocalDateTime oneHourAgo); + List findAllSchedulesWithoutClockOut(LocalDateTime standardTime); Boolean existsByRegularGroupId(Long regularGroupId); @@ -42,4 +43,20 @@ SELECT CASE WHEN COUNT(s) > 0 THEN TRUE ELSE FALSE END AND s.endTime >= :startTime """) Boolean existsOverlappingSchedule(Long staffId, LocalDate workDate, LocalDateTime startTime, LocalDateTime endTime); + + @Query(""" + SELECT s AS schedule, f.name AS staffName, st.boss.id AS bossId, st.id AS storeId + FROM ScheduleEntity s + JOIN StaffEntity f ON s.staff.id = f.id + JOIN StoreEntity st ON f.store.id = st.id + LEFT JOIN s.attendance a + WHERE s.startTime < :standardTime + AND a IS NULL + AND NOT EXISTS ( + SELECT 1 FROM NotificationEntity n + WHERE n.type = 'SCHEDULE' + AND n.metaId = s.id + ) + """) + List findLateSchedulesWithoutAlarm(LocalDateTime standardTime); } diff --git a/storage/src/main/java/com/mangoboss/storage/schedule/projection/ScheduleForLateClockInProjection.java b/storage/src/main/java/com/mangoboss/storage/schedule/projection/ScheduleForLateClockInProjection.java new file mode 100644 index 00000000..8e5a1610 --- /dev/null +++ b/storage/src/main/java/com/mangoboss/storage/schedule/projection/ScheduleForLateClockInProjection.java @@ -0,0 +1,10 @@ +package com.mangoboss.storage.schedule.projection; + +import com.mangoboss.storage.schedule.ScheduleEntity; + +public interface ScheduleForLateClockInProjection { + ScheduleEntity getSchedule(); + String getStaffName(); + Long getBossId(); + Long getStoreId(); +}