From 3b16c358ee105a300d10db69cef178bbac8cf057 Mon Sep 17 00:00:00 2001 From: eunsxx <88652027+eunsxx@users.noreply.github.com> Date: Wed, 19 Feb 2025 17:26:10 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[FEAT]=20=EC=8B=9D=EB=8B=A8=20=EA=B8=B0?= =?UTF-8?q?=EB=A1=9D=20=EC=8B=9C=20=EC=9C=A0=EC=A0=80=EC=9D=98=20record=5F?= =?UTF-8?q?complete=20=EA=B0=92=20true=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../record/repository/RecordRepository.java | 1 + .../record/service/RecordServiceImpl.java | 22 +++++++++++++++++++ .../java/umc7th/bulk/user/domain/User.java | 8 ++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/main/java/umc7th/bulk/record/repository/RecordRepository.java b/src/main/java/umc7th/bulk/record/repository/RecordRepository.java index a3ffbea..f52fa76 100644 --- a/src/main/java/umc7th/bulk/record/repository/RecordRepository.java +++ b/src/main/java/umc7th/bulk/record/repository/RecordRepository.java @@ -22,4 +22,5 @@ public interface RecordRepository extends JpaRepository { @Query("SELECT r FROM Record r WHERE r.user = :user AND r.date = :date") List findByUserAndDate(@Param("user") User user, @Param("date") LocalDate date); + boolean existsByUserAndDate(User user, LocalDate date); } \ No newline at end of file diff --git a/src/main/java/umc7th/bulk/record/service/RecordServiceImpl.java b/src/main/java/umc7th/bulk/record/service/RecordServiceImpl.java index 991e08b..1a2187b 100644 --- a/src/main/java/umc7th/bulk/record/service/RecordServiceImpl.java +++ b/src/main/java/umc7th/bulk/record/service/RecordServiceImpl.java @@ -20,6 +20,7 @@ import umc7th.bulk.recordedFood.entity.RecordedFood; import umc7th.bulk.recordedFood.repository.RecordedFoodRepository; import umc7th.bulk.user.domain.User; +import umc7th.bulk.user.repository.UserRepository; import umc7th.bulk.user.service.UserService; import java.io.IOException; @@ -39,6 +40,7 @@ public class RecordServiceImpl implements RecordService { private final S3Service s3Service; private final AiCallService aiCallService; private final UserService userService; + private final UserRepository userRepository; @Transactional public RecordResponseDto createRecord(RecordRequestDto.Create requestDto) { @@ -56,6 +58,10 @@ public RecordResponseDto createRecord(RecordRequestDto.Create requestDto) { throw new IllegalArgumentException("이미 해당 날짜와 끼니에 대한 기록이 존재합니다."); } + // 사용자의 해당 날짜 기록 확인 + boolean hasRecordToday = recordRepository.existsByUserAndDate(user, requestDto.getDate()); + + // 사용자의 끼니(MealType)에 해당하는 식단 데이터 조회 List mealMappings = mealMealItemMappingRepository.findByMeal_LocalDateAndMeal_Type( requestDto.getDate(), requestDto.getMealType()); @@ -78,6 +84,12 @@ public RecordResponseDto createRecord(RecordRequestDto.Create requestDto) { Record savedRecord = recordRepository.save(record); + // 하루에 한 번이라도 기록하면 record_complete = true 설정 + if (!hasRecordToday) { + user.markRecordComplete(); + userRepository.save(user); + } + // MealItem을 기반으로 RecordedFood 생성 List recordedFoods = mealMappings.stream() .map(MealMealItemMapping::getMealItem) @@ -152,6 +164,10 @@ public RecordResponseDto createNotFollowedRecord(RecordRequestDto.CreateNotFollo // MealType 변환 MealType type = requestDto.getMealType(); + // 사용자의 해당 날짜 기록 확인 + boolean hasRecordToday = recordRepository.existsByUserAndDate(user, requestDto.getDate()); + + String uploadedImageUrl = null; String gptRawResponseString = null; @@ -256,6 +272,12 @@ public RecordResponseDto createNotFollowedRecord(RecordRequestDto.CreateNotFollo Record savedRecord = recordRepository.save(record); log.info("✅ Record 저장 완료: recordId={}", savedRecord.getId()); + // 하루에 한 번이라도 기록하면 record_complete = true 설정 + if (!hasRecordToday) { + user.markRecordComplete(); + userRepository.save(user); + } + // Response 생성 return RecordResponseDto.builder() .recordId(savedRecord.getId()) diff --git a/src/main/java/umc7th/bulk/user/domain/User.java b/src/main/java/umc7th/bulk/user/domain/User.java index cf5cbdb..9c71dec 100644 --- a/src/main/java/umc7th/bulk/user/domain/User.java +++ b/src/main/java/umc7th/bulk/user/domain/User.java @@ -76,7 +76,7 @@ public class User extends BaseTimeEntity { private String favoriteFood; @Column(nullable = false, name = "record_complete") - private boolean recordComplete; + private boolean recordComplete = false; @Column(nullable = false, name = "access_token") private String accessToken; @@ -167,4 +167,10 @@ public void setGroup(Group group) { group.getMembers().add(this); } } + + public void markRecordComplete() { + if (!this.recordComplete) { + this.recordComplete = true; + } + } } From cce9d631809d300e95e62ed584ecdca34382ba68 Mon Sep 17 00:00:00 2001 From: eunsxx <88652027+eunsxx@users.noreply.github.com> Date: Wed, 19 Feb 2025 17:38:37 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[FEAT]=20=EB=A7=A4=EC=9D=BC=20=EC=9E=90?= =?UTF-8?q?=EC=A0=95=20=EC=9C=A0=EC=A0=80=EC=9D=98=20record=5Fcomplete=20?= =?UTF-8?q?=EA=B0=92=20false=EB=A1=9C=20=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/umc7th/bulk/BulkApplication.java | 2 + .../service/RecordCompleteResetService.java | 28 +++++++++++ .../bulk/user/repository/UserRepository.java | 8 ++++ .../RecordCompleteResetServiceTest.java | 48 +++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 src/main/java/umc7th/bulk/record/service/RecordCompleteResetService.java create mode 100644 src/test/java/umc7th/bulk/record/service/RecordCompleteResetServiceTest.java diff --git a/src/main/java/umc7th/bulk/BulkApplication.java b/src/main/java/umc7th/bulk/BulkApplication.java index d3ea613..ea2dc09 100644 --- a/src/main/java/umc7th/bulk/BulkApplication.java +++ b/src/main/java/umc7th/bulk/BulkApplication.java @@ -4,9 +4,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableJpaAuditing +@EnableScheduling public class BulkApplication { public static void main(String[] args) { diff --git a/src/main/java/umc7th/bulk/record/service/RecordCompleteResetService.java b/src/main/java/umc7th/bulk/record/service/RecordCompleteResetService.java new file mode 100644 index 0000000..7b763ef --- /dev/null +++ b/src/main/java/umc7th/bulk/record/service/RecordCompleteResetService.java @@ -0,0 +1,28 @@ +package umc7th.bulk.record.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import umc7th.bulk.user.repository.UserRepository; + +@Slf4j +@Service +@RequiredArgsConstructor +public class RecordCompleteResetService { + + private final UserRepository userRepository; + + /** + * 매일 자정에 record_complete 값을 false로 초기화하는 배치 작업 + */ + + @Transactional + @Scheduled(cron = "0 0 0 * * ?") + public void resetRecordComplete() { + log.info("매일 자정 record_complete 값 초기화 시작..."); + int updatedCount = userRepository.resetRecordComplete(); + log.info("✅ 초기화 완료: {}명의 record_complete 값을 false로 변경", updatedCount); + } +} diff --git a/src/main/java/umc7th/bulk/user/repository/UserRepository.java b/src/main/java/umc7th/bulk/user/repository/UserRepository.java index 7d6e8a5..3f1c54c 100644 --- a/src/main/java/umc7th/bulk/user/repository/UserRepository.java +++ b/src/main/java/umc7th/bulk/user/repository/UserRepository.java @@ -1,6 +1,9 @@ package umc7th.bulk.user.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; import umc7th.bulk.user.domain.User; import java.util.List; @@ -14,4 +17,9 @@ public interface UserRepository extends JpaRepository { List findByGroupGroupIdAndRecordCompleteTrue(Long groupId); // 해당 그룹 id 에서 오늘 기록 달성한 사용자 리스트 Optional findByKakaoId(String kakaoId); Optional findByEmail(String email); + + @Modifying + @Transactional + @Query("UPDATE User u SET u.recordComplete = false") + int resetRecordComplete(); } diff --git a/src/test/java/umc7th/bulk/record/service/RecordCompleteResetServiceTest.java b/src/test/java/umc7th/bulk/record/service/RecordCompleteResetServiceTest.java new file mode 100644 index 0000000..9b1ba55 --- /dev/null +++ b/src/test/java/umc7th/bulk/record/service/RecordCompleteResetServiceTest.java @@ -0,0 +1,48 @@ +package umc7th.bulk.record.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import umc7th.bulk.user.domain.User; +import umc7th.bulk.user.repository.UserRepository; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + + +class RecordCompleteResetServiceTest { + + @InjectMocks + private RecordCompleteResetService recordCompleteResetService; + + @Mock + private UserRepository userRepository; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void testResetRecordComplete() { + // given + User user1 = User.builder().id(1L).email("user1@example.com").recordComplete(true).build(); + User user2 = User.builder().id(2L).email("user2@example.com").recordComplete(true).build(); + List users = Arrays.asList(user1, user2); + + // when + when(userRepository.resetRecordComplete()).thenReturn(2); + + recordCompleteResetService.resetRecordComplete(); + + // then + verify(userRepository, times(1)).resetRecordComplete(); // 1번 실행됐는지 검증 + } + + +} \ No newline at end of file From 800b11b1a63334f13f7c187322bd854dc66f7539 Mon Sep 17 00:00:00 2001 From: eunsxx <88652027+eunsxx@users.noreply.github.com> Date: Wed, 19 Feb 2025 20:07:28 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[FEAT]=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EA=B8=B0=EB=A1=9D=EA=B3=BC=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EC=8A=A4=ED=85=8C=EC=9D=B4=EC=A7=80=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keystore.jks | Bin 0 -> 2744 bytes keystore.p12 | Bin 0 -> 2712 bytes .../record/service/RecordServiceImpl.java | 48 ++++++++++++ .../bulk/stageRecord/entity/StageRecord.java | 2 + .../repository/StageRecordRepository.java | 4 + .../bulk/user/repository/UserRepository.java | 15 ++++ .../command/UserCommandServiceImpl.java | 22 +++++- src/main/resources/keystore.p12 | Bin 0 -> 2744 bytes .../record/service/RecordServiceImplTest.java | 71 ++++++++++++++++++ 9 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 keystore.jks create mode 100644 keystore.p12 create mode 100644 src/main/resources/keystore.p12 create mode 100644 src/test/java/umc7th/bulk/record/service/RecordServiceImplTest.java diff --git a/keystore.jks b/keystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..fbdab8277f7176e742c5e852dafc2e5a327570cd GIT binary patch literal 2744 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 Y7l#Ek6^xTB(xD9RGf*Jo{eKbkFQ*LuA^-pY literal 0 HcmV?d00001 diff --git a/keystore.p12 b/keystore.p12 new file mode 100644 index 0000000000000000000000000000000000000000..72f600d8a95ffc2bf18c5e68621f63aeb3a1a8a7 GIT binary patch literal 2712 zcma);XE+;*8po4Jh412y#D7eTZT0D_mA)+t^e=tczw zii4S-z_$1eoA|K_yN@}%_H1&%c<`HG>=W19Hc?adCGJzNd35EjYR+wW(p(UEJ2%MA zrESH0i@L!L$MreM1E?yUNMYMv%Z=mo z*9*GTm0xTwUvvgDD+cVCx#MlwO|1u5#qDfhVu+Z*htELkooktt2&1QPWzVHaVF^;) zqN~a=<;q#9#bAQM%7i%B0F%VNh)bOo+4w^NzRz+$hb2mMxzTv$`+#3oCt0x3y7OtL z6D#xCU#bNOoa%(JJ5KgoK!~2N#}*PTbm9QNpF6PfGMEh#prdBYqBWQ?dSs`8|8n7)#j(ZQ5elmN`r{lOS0gvtg6(6jF&1M&Bt_lxEM93&)^+*^n+OsLm1=NYP0xRU- zhiIPgY$ZG1OZT(>W_2gHS2_BFd|=qbnQFV{EkQ!YwZ@NO;VM9wrakXJplzW!_+jgH z@~A=eODH{{bgu$_1|nA9*KxRKVvypC5*RMPp~fz@=?j{8!plFP3B{j|J88GA(?|AN zb%x8Fo%u$_2OjlW&ODAyYb7$rR+($%H-2lod@6qv)og*$iK(vJP65t~ov&O}ki<## zw!s$Y%kMl|N~Qox#8wx|`*e?UW^9KpmXXgtizJhVSjO}o7sx2RwtsbaZ@Mpo!o|BD zb@*LW1C_>et}#N?UETWb_etC7eMxEJ*Yqmeq?rv}>Ia9RO@uy~zX=EGCve@ajeeh-YQ1JW_m`4G^0~ z?a6!E;VGwAzD;Bo_a3us89VsUsjPyaY_@+xcNGd|8jDt`$Uh4~drNzHw~I$OU^U;B zD33)E-ld){AFua2-Q=zAAG#itAz??W^+J8d=)l^!R)a@><7;w^l+B4oXq~|BY~ocL zuV@cmc)eyZ&v!x6;}`_bf=tYTG>a^zE3M}~hDadQJcNF00jRQKQ?C?VX@g;xL&S&k z;gT4ibeLopkAR!W?e5x=!~AnpcS0-I)J+MlIxiWa@+5_&ab)ap7|KUc7Os=G)poIcrKwDEjmbrmQoil{{h~(kM$Gu$ZAju`*4IqA79G zNBW2NZV=lMXe)Kj$*_59GiYF;lV0AmLzyfg25Bbf(z4@gxdob3K?Ft||Ni+QH2gOS z^1Do{Xmmom-1D8hvNsv&6Zr$wl8$1H@%;Fx1kbM-84UTIxq(BZ=DoKO(Iw5Bar7W* zH31`kF>uS_wQMx9$9Z`OK03xRAnFE?ebMA^Yi*8yB-C{+a~~X|T^T1pY!KgvbtRHy zHm;^3Q3&pzaY@UHWa4801Ofa3fdDT64&Z?h_$9)TtYDVgUcPSpNCjC%MR}y0tb#03 z7J&x`{9K};F2jQ{Kac|m2>8*geks8J71QgljOPknIRqZmbazE@k$ad%VrTxJn6_lL zS+#ANrAWS_#^Ok_JJEQmrKYS;w78sGVNA4Mhp4ltB(?Uz)8wqE;J%8_V*J(C>8SZM z;{NHI+h^Bw%n7o2tMjYl{Zvhj4Ifi7+&;9%jJzjOHL>6-gY;RSM*G*qz%pP(lrN_Fnk5au(zhBx%1sj`J>`%<< z-gN_2-e1jsqG6itz_sMh7SLGGw!d)efmF^##7!YC?Z~&S_gePv7B>*am-t%(|4PQw@3e4B&h|=8JLyslg zjN^eDHAS9Q<_50kGQlt3fsY*6vMEJ`U5ufeFeV;uxLK*S zp_D%T7JZ7f<*N_I>b=vkaJ>&@S1Ay zOafZxS!6zdN_uD4w4^%oID~ETO*0ou4yon59{71sVTG_FaBGG}+kXGgAz}3>4r>d) z?iudrU7$&_GNhkV%LZ)W+ksq^`6B4VsDN;^60jP9WkNAp!Tw7F$(l~-rulr3ZKJ*w z%qm8oTIA%uJY|&PcEOqDwGcqI<58}tWHA?tFPMCC?@^S6nX!K1gW*DKrpFyRi?L=6 z9fkz+j-W7!?l5NhBcJ8|S^1u!vl;jD&)nvazwHAZw4& recordedFoods = mealMappings.stream() .map(MealMealItemMapping::getMealItem) @@ -278,6 +288,8 @@ public RecordResponseDto createNotFollowedRecord(RecordRequestDto.CreateNotFollo userRepository.save(user); } + checkAndAdvanceStage(user.getGroup()); + // Response 생성 return RecordResponseDto.builder() .recordId(savedRecord.getId()) @@ -372,5 +384,41 @@ public RecordResponseDto.TodaySummary getTodayRecord(User user) { .build(); } + public void checkAndAdvanceStage(Group group) { + // 현재 그룹에서 recordComplete = true인 유저 수 확인 + int recordedCount = userRepository.countByGroupAndRecordCompleteTrue(group); + + if (recordedCount >= 5) { + advanceStage(group); + } + } + + private void advanceStage(Group group) { + // 현재 그룹의 가장 최신 스테이지 가져오기 + StageRecord currentStageRecord = stageRecordRepository + .findTopByGroupOrderByStageNumberDesc(group) + .orElseThrow(() -> new CustomException(GeneralErrorCode.GROUP_NOT_FOUND_404)); + + // 현재 스테이지 완료 처리 + currentStageRecord.completeStage(); + stageRecordRepository.save(currentStageRecord); + + // 그룹의 현재 스테이지 증가 + group.advanceStage(); + groupRepository.save(group); + + // 새로운 스테이지 기록 생성 + StageRecord newStageRecord = StageRecord.builder() + .group(group) + .stageNumber(group.getCurrentStage()) + .totalUsers((int) userRepository.countByGroup(group)) + .recordedUsers(0) // 새로운 스테이지이므로 기록된 사용자 0명부터 시작 + .isCompleted(false) + .build(); + + stageRecordRepository.save(newStageRecord); + } + + } \ No newline at end of file diff --git a/src/main/java/umc7th/bulk/stageRecord/entity/StageRecord.java b/src/main/java/umc7th/bulk/stageRecord/entity/StageRecord.java index 3b6f578..c4bd3c5 100644 --- a/src/main/java/umc7th/bulk/stageRecord/entity/StageRecord.java +++ b/src/main/java/umc7th/bulk/stageRecord/entity/StageRecord.java @@ -50,6 +50,8 @@ public void increaseRecordedUsers() { this.recordedUsers++; } + public void increaseTotalUsers() { this.totalUsers++; } + // 스테이지 완료 처리 로직 public void completeStage() { this.isCompleted = true; diff --git a/src/main/java/umc7th/bulk/stageRecord/repository/StageRecordRepository.java b/src/main/java/umc7th/bulk/stageRecord/repository/StageRecordRepository.java index c8f4b3f..b3a5ff2 100644 --- a/src/main/java/umc7th/bulk/stageRecord/repository/StageRecordRepository.java +++ b/src/main/java/umc7th/bulk/stageRecord/repository/StageRecordRepository.java @@ -1,10 +1,14 @@ package umc7th.bulk.stageRecord.repository; import org.springframework.data.jpa.repository.JpaRepository; +import umc7th.bulk.group.entity.Group; import umc7th.bulk.stageRecord.entity.StageRecord; import java.util.List; +import java.util.Optional; public interface StageRecordRepository extends JpaRepository { List findByGroupGroupIdOrderByStageNumberAsc(Long groupId); + + Optional findTopByGroupOrderByStageNumberDesc(Group group); } diff --git a/src/main/java/umc7th/bulk/user/repository/UserRepository.java b/src/main/java/umc7th/bulk/user/repository/UserRepository.java index 3f1c54c..b6de523 100644 --- a/src/main/java/umc7th/bulk/user/repository/UserRepository.java +++ b/src/main/java/umc7th/bulk/user/repository/UserRepository.java @@ -3,7 +3,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; +import umc7th.bulk.group.entity.Group; import umc7th.bulk.user.domain.User; import java.util.List; @@ -22,4 +24,17 @@ public interface UserRepository extends JpaRepository { @Transactional @Query("UPDATE User u SET u.recordComplete = false") int resetRecordComplete(); + + // 특정 그룹 기록 달성한 인원 수 조회 (오늘 기록 완료한 인원 수) + @Query("SELECT COUNT(u) FROM User u WHERE u.group = :group AND u.recordComplete = true") + int countByGroupAndRecordCompleteTrue(@Param("group") Group group); + + // 특정 그룹 총 인원 수 조회 + @Query("SELECT COUNT(u) FROM User u WHERE u.group = :group") + int countByGroup(@Param("group") Group group); + + + + + } diff --git a/src/main/java/umc7th/bulk/user/service/command/UserCommandServiceImpl.java b/src/main/java/umc7th/bulk/user/service/command/UserCommandServiceImpl.java index b86360d..e6ecdaf 100644 --- a/src/main/java/umc7th/bulk/user/service/command/UserCommandServiceImpl.java +++ b/src/main/java/umc7th/bulk/user/service/command/UserCommandServiceImpl.java @@ -9,6 +9,8 @@ import umc7th.bulk.global.jwt.util.JwtProvider; import umc7th.bulk.group.entity.Group; import umc7th.bulk.group.repository.GroupRepository; +import umc7th.bulk.stageRecord.entity.StageRecord; +import umc7th.bulk.stageRecord.repository.StageRecordRepository; import umc7th.bulk.user.domain.User; import umc7th.bulk.user.dto.UserRequestDTO; import umc7th.bulk.user.dto.UserResponseDTO; @@ -30,6 +32,7 @@ public class UserCommandServiceImpl implements UserCommandService { private final JwtProvider jwtProvider; private final BulkCharacterRepository bulkCharacterRepository; private final GroupRepository groupRepository; + private final StageRecordRepository stageRecordRepository; @Override public UserResponseDTO.UserTokenDTO signup(UserRequestDTO.SignupDTO dto) { @@ -69,9 +72,26 @@ public UserResponseDTO.UserTokenDTO signup(UserRequestDTO.SignupDTO dto) { .currentStage(1) .endDate(LocalDateTime.now().plusDays(7)) // 그룹 종료일 7일 후 설정 .build(); - return groupRepository.save(newGroup); + groupRepository.save(newGroup); + + StageRecord firstStage = StageRecord.builder() + .group(newGroup) + .stageNumber(1) + .totalUsers(1) + .recordedUsers(0) + .isCompleted(false) + .build(); + stageRecordRepository.save(firstStage); + + return newGroup; }); + if (!groupRepository.findGroupWithSpace().isPresent()) { // 기존 그룹인지 확인 + StageRecord latestStage = stageRecordRepository.findTopByGroupOrderByStageNumberDesc(group) + .orElseThrow(() -> new RuntimeException("StageRecord not found for existing group.")); + latestStage.increaseTotalUsers(); + stageRecordRepository.save(latestStage); + } // User 저장 (BulkCharacter 포함) diff --git a/src/main/resources/keystore.p12 b/src/main/resources/keystore.p12 new file mode 100644 index 0000000000000000000000000000000000000000..3eb158f68d4e7fa5da0035b786c0aaece2469e01 GIT binary patch literal 2744 zcma);X*d*)7RG1Bj6sa08OlT=62*)rV_!x_7!B9H(;(|$#6*O#j44Y=c15z6WRGM| z*7{o#21zLUI+d;4eeQkwKljtUAI@{0^Lx*GKEBUE(YUHXKsFSO%YmI!CiZgdcOD=V zm`md#f@xfazp);Q1}Xn93GxU`gJk{2X}{|}`;q^+xVeC!TpC2{H&jEp{c%8eP}V4= zzejGAEEs;I>U`*_hffG}cR^O=OcLX!@a1U`=nNkSD2C!@=lJ(U5GMqH5@F|bioFbU zWdj3czUNVZ1!_;1=_lM#6y)5S?dmW}{ z-RY|+CAbuIMBgCAc+jTggLS1;xQ12;Im{tnn;}6p7+v@L(EHVIDDOvh?%vd_rv3U? zPxLR@s=l>XhY+LqZ26Jl@li$~eYrRA%lb>cQk~R#&cyoE_~E~Dj!o=Ra&&Ld8uOSZ zI|Z(im$&ZY;9bG}2n{*&JOCvD7x9bt_~2lbO(pUuhOIG^TTz%TS_C%);=A2M^KjK~Ch>Md47C$rd_A@m%j&|LU(j|J_~#5dRO<#6?Sb9&xz+NQ49Wk$kK6~ zkfNtL>G;iO%wNg1De>hKe0Sq?A}>S)zW7#y$QD6LF3UTnkZ112Y-B78H)FZo;z_`M zTRFdF?}gK(&{ZQVOiPui^U%hlQ&rk-!mXbR$8QC@i~A7!$*s&>)sO1_KCAJu$Ozfn z&o$dHjgBWk_8wyIT;{u|$;lT8REx{=M<5Xzxv48Qvmf;GX`M@5`+bWhuR!@D%ZhlN zC`ybU>T}B7m(0?2rwK;L`JF2tS3YU0!4#DHHWk{oOkhFRiE%#>+tr+jR&D0ThP$OJGtR0$nIVyl_SD&EkZb-o;j{<2UspU=2~qefWLv z>c*k!OeOfKgSK9KlMj%`yNDrO z>QCp!0>Ry`mj;9#k>#@mME}lV5rec=bn`Ly*S_0qa?KiNE70;k=aID(=?q=+aBfmv z64QCdJopr~jSF7p5w&+@FfBMn1#9U}wuZ^Dn>JJD?NUGf2PLU00)0)>tcduDH zWm`SV@@crNa0wCeoY);he35nd=0@Jf$#lUg0kn*z_j1!76=IV-Kc*n!2cD~EiDltm^a6@=`rg)DB)*IfjtDn|0kv= zd%4OFAh$mt-1CC!yU`mFG%$dQwQUZ5FqT9TwdT#Y?doa3n6B5}fSG9X%I4S*cw+Rt z25PJ+aug0ByoXNg2uT*M74)r0*@~y+nCg4_;=3ir@?m_7G2%YoNCH!(>Lo5Q!9rHq zFgkl_&JvB>{1|)yOL&qcgl&iE+u+w#N?`Zd^|7*s0$#5YIjU51-i6!rDj3{2#u$RQ zlysN2J*sp=m05GRaMF`3Vk+GWTrAJ4qlEN$8ba|{?>G(9W!?NLhwn9yQMIH&y;sTP zf&K~3=b@AHn&RMs)BA;w^4Aw_*Rih+DYa*n-`DKb9k@IbI;19FD*Al`61xP4(N4e3cWP}txQaEO`b?w4 z`I7}yDc=`a?hYXeE8Ldu_OrJaS!Ux-L85DS^eacPf;-_JJTOfkX3|w(zxzOSRMzq# z&RO8|;gENbREVnlxsqwYw+?e1QpO9ddox&&e6rCOyqu|qwLqA^UzJv+j@>s zwlH5Hf6L&xfuOm;h=y7WV0&i%fyBrIS(22Om%{06sRv`vAa_X8=uYf&n}VSaqNc|Y_GaC{ z_ifVORPGG=HY#RzwzKj$;M0MQ^(P>sD*^Y+S~eo@xSF!~Cu`0R*x?vXDF*w`4mhLw zzes~&`Gre>MmEwCL%N`R?z7#Bom)rN)*pMe_g-$ z0@vBygt0IIe+p_|#B0w(R=6>sB9!=~eKf^C$1^E2((A-zjb-nikD5Bv_j6@P{CvQf z_SUosd(xV#w!4W|QlV;48mj?XQe|KhE;R104rfh1PK|efPalOh2AS90X>v3j?w{U9 zY-AA&wgh)G9W`iEx*!qVI!)V0uDoaMxjYnav||G{={mey&O(hV(EwWg&d^6_n*O#@ z#hWTV5j?+&^w=s+x3d7$iu^L8s)h}_#Vn>n^HdWxe$JJ1N)f5KiUXyWoO7+5aIF~d zNp}4w0p|>7T6T0ZB;XJ0CucmZDDoc(g2N0!!pO;{9svDm3bseb-l^o~gb&8+U_~f0 zRRU#%LZf*8d~+Zm1OOJB2n;o%KK->{A(Gfg8ysU-<_W!ZlWgS2lc_>ZM|MPj;YlrA YS%mz_bk3@-*#%&5jjnW7?Y|=EpZo9e-v9sr literal 0 HcmV?d00001 diff --git a/src/test/java/umc7th/bulk/record/service/RecordServiceImplTest.java b/src/test/java/umc7th/bulk/record/service/RecordServiceImplTest.java new file mode 100644 index 0000000..60cc669 --- /dev/null +++ b/src/test/java/umc7th/bulk/record/service/RecordServiceImplTest.java @@ -0,0 +1,71 @@ +package umc7th.bulk.record.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import umc7th.bulk.group.entity.Group; +import umc7th.bulk.group.repository.GroupRepository; +import umc7th.bulk.stageRecord.entity.StageRecord; +import umc7th.bulk.stageRecord.repository.StageRecordRepository; +import umc7th.bulk.user.domain.User; +import umc7th.bulk.user.repository.UserRepository; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class RecordServiceImplTest { + + @InjectMocks + private RecordServiceImpl recordService; // 테스트할 대상 + + @Mock + private UserRepository userRepository; + + @Mock + private StageRecordRepository stageRecordRepository; + + @Mock + private GroupRepository groupRepository; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void testStageAdvancementWhenFiveUsersRecord() { + // given + Group group = Group.builder().groupId(1L).groupName("Test Group").currentStage(1).build(); + + User user1 = User.builder().id(1L).group(group).recordComplete(true).build(); + User user2 = User.builder().id(2L).group(group).recordComplete(true).build(); + User user3 = User.builder().id(3L).group(group).recordComplete(true).build(); + User user4 = User.builder().id(4L).group(group).recordComplete(true).build(); + User user5 = User.builder().id(5L).group(group).recordComplete(true).build(); + + StageRecord currentStage = StageRecord.builder() + .group(group) + .stageNumber(1) + .totalUsers(10) + .recordedUsers(4) // 현재 4명 기록 완료 (5명 달성 시 스테이지 변경) + .isCompleted(false) + .build(); + + // when + when(userRepository.countByGroupAndRecordCompleteTrue(group)).thenReturn(5); + when(stageRecordRepository.findTopByGroupOrderByStageNumberDesc(group)).thenReturn(Optional.of(currentStage)); + + recordService.checkAndAdvanceStage(group); + + // then + assertTrue(currentStage.isCompleted()); // ✅ 기존 스테이지가 완료됐는지 확인 + verify(stageRecordRepository, times(2)).save(any(StageRecord.class)); // ✅ 새로운 스테이지 저장 확인 + verify(userRepository, times(1)).countByGroupAndRecordCompleteTrue(group); // ✅ 기록 완료 인원 체크 확인 + verify(groupRepository, times(1)).save(group); + } + +} \ No newline at end of file From 4e4d55838e415e249dc919ad599663de935cda14 Mon Sep 17 00:00:00 2001 From: eunsxx <88652027+eunsxx@users.noreply.github.com> Date: Wed, 19 Feb 2025 20:52:07 +0900 Subject: [PATCH 4/6] =?UTF-8?q?[ADD]=20key=20=ED=8C=8C=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keystore.jks | Bin 2744 -> 0 bytes keystore.p12 | Bin 2712 -> 0 bytes src/main/resources/keystore.p12 | Bin 2744 -> 2712 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 keystore.jks delete mode 100644 keystore.p12 diff --git a/keystore.jks b/keystore.jks deleted file mode 100644 index fbdab8277f7176e742c5e852dafc2e5a327570cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2744 zcma);c{J1y_s3_L8ODr#sjNdvjqNkC6Giqldm+TophnwFWF1@CWv>`QmMn$PkSxhg zYAiFQhE&MDGvw)ae$VN9p1+>wk9+R9ulIf5Ki}s9B#t^3Fe^afxCDcvV~k_AIKgb- zd=iHhgv4R?2O9w-Xw`p6P%?xBee?%s{i!q<;@>VL2bd+F1U>TyY6ISX9Z*i-0-*lS zhy-LI0vvcG9{j}Ch$epu)psZGLBR0+G!_;a9u_bPK*HGn{~`+<3IfDnaQ7HvFqRbp zMnialZd_lJG2wm2Sgxq6@rciXkRb1`-!K~&xv#0RPWZUruIS2pA5b)hU4hCv9;WeB zkCvV_P&Y_!zq}ywDKHwEy87NPQ=#lr%w3W$?WYUOWGFRlyT^1LVPMDyp0Y3l7i!=A z#(hvZ>%&yurRDcwj}?GKjH26woq`e%S(gzjv2K<2glsp4OxqVaPF3{56Z|UY4Tq}P zUU;hllct?~_mZnc@xjtbn?V%o_K>7h3Sn1itz59-^yTfSw)oi4_?$^0Ans%G0jXPO zK5M*!BVtY_k()Q-d3d3PIGAfjH0X`ow`uo1MFikL5F?a09#w4DbCM3%Xl{R|!X3f> zS#0AH?r~b~7!^4H`!Q8V=KyNL1zcjvLQ4+SzO)&;^F!NIr$=IPebVVf<6gZWg3e(d zCy}Qly&^d+hj_IsB&INKHO%D4b!?_4Oa}haXBR$Y!{i;PY70$W@}ao;KM*5d)8wqd z7k03R?(Bt6=zXqFyVf>S=h5MGbXm$Wohh4RJ3y4ed3HJNsXB!Bhq26)YQ%pOS*zq=h>WGH=IkUGAh)-;fjRCsJ! zOzD{{a#0@xRvL_}ZxpE#FfH*baju=&@!Ze8ptmSgyHcn~pUxpav9zud^!fB^TZ`fy z``I7fH!JjAM1Klr`NeMCq5nEovxXi#{dO$#hDwF6K=%8nmX@AWBHdDBHpQxjd*$iL z0Rv$zT~zB9y~fF=b=lUNr%}FZPibyEzvYLNn)@Uy5JtW0v$1SiJ62tnBD!e$rFXH5IyYj?(Dfzo3}N3bip9?88+^c=o}}CAUSMEe^h~HrV>kdXM&YDJi;5jyJOtW z%Qp8ltDNgf7n=uyY_!uy0gCR7h<0DB(AzKkrJK%-?`FE*5;+#tzzfjfO(uC2~qs3N~&>Q(q=-_b7xUYifUJK~1p#EIR0k z=@$^8h@@_sDQu=_H|0wie1Hq$^rd!9V0Mj=1OR0MFDTyYoy|k6+~;7GqOKMbV8l6I`^&kb zP@cE|xNm7xoa-45_2Xmpm@RgX>|9wB{hX!Ie8z3BLFbFs36HCOa<4^3@twEkOd04Z z*c;njZ2KlV?r$>eblzX;`mfx5UR^oDn^~M85! znIE00V>{ptsK!Qzo3A_{-_~nyl4~zDwzOj~i?R`9NP@Bp!hiC$Lp`A357|P~{e|K< zotkQ|V9o#{f8!D^fZ-BHf^LEEpsOHHkO$}%Ao-6dh!KGB+2O8YQ5dyT8XBsYQ%V|2 zfC@l@r2buEgXNPTq(3N>1q}Mri2o?y{}$6wnnNN;XFK=a1Bq8+d*DC+oP zd+%xqr*idgnL5#sp=AN&Bi0w9hVx|Q%jxuba*(;+?B*e^SPy$y zO&6Yz=hxKUH1EhAD+nLuJ1h;P&QEE_9?DYLj8v$jvd%~c<;M>wvFaMUA4GDoQR|jh z3+h#?XaqCHYfFLey}$F4qIdoA_tJnk-bJDAiKbLbTonEU;04x+H!vBOAL&x)eJPX6 zRItO-5obBGG{mB9hul#tVm(g}FRCwG+>SCHipI)s*m8?DIa43nqG01D57< zWw7;%8lm^5H>-%n@mXoIKR%L1iWr`!msVMIDKD$kKe$NyefOHZ;XP1E-LIhd{S|Rj9FIZCwYbZL#O%V?| z;?gW>!&DjV*J?=#ZS@b=z0-FrBP7z@5UHyIE(s;yHrcr*GvxuhT=GdFfpB70z0?KW zRu`peJn42@L+Hv4eSx6stk=%c5Zm8)1X12Z|PJhPd z*lXNbIK@>uL8E<57-@=q1a>sE@=~%38K7Q>5$*spl)wXMC(O zp~rff*Iz_$&*cygo!H3u8H{^M@3-v~efy1h@_V&kFiyO>>{=7Pp|f$xv!@~c3*S-s z3+Vm_vDhUB>7}xHUW)Fk(3>~wh&=;|5ry`5c{8}Xy&$#47CfDC+tP{&kStv7@Ab>1 z^;?E?aLMr(Jn4umMogKRgFopAnmX;`GlH*EI6a;O4SsQ&DI7n7)H`X zM8s2G>wusj#7zRn9Pn;)=XHt%BSK33;o#}C3Fkn|8Z}SPG>$y@^I{{dF?~emTy^&6 z2cfy9r>P2$?ik1q-S+hJ9bC|oRMjNJrAcr#w@LNU7EYIWIXjfr>)rt`cc7Px9hFxb z@V$YHd#`-r*0rNSAGwYEo1elaV3RXv_F3|Ly?pKX`JPP(zC$G91QjJ-pcqS!-Wz`A zdHI7%^3`$FNMiErmIo#`IvGW|L4f@Jl=Fp3<#Vz>A2W9Czgie=R~ooZH#NFi`fr|e z8PYIL-~1SH-6#4=dM`GC=v!KBE@vKQhN`s4y010y;b?5po1WzWDzoh2^ztD8=!K5& z=5W9QzyO?ozd05#6a+yfE4XbixA)SCrxm;Q0#-Sc?GSRy!94N{!L*gFF8(5jfT>9A Y7l#Ek6^xTB(xD9RGf*Jo{eKbkFQ*LuA^-pY diff --git a/keystore.p12 b/keystore.p12 deleted file mode 100644 index 72f600d8a95ffc2bf18c5e68621f63aeb3a1a8a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2712 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 delta 2550 zcmVrDd8)K^X726<+5lMX zeR+3BX}YG=yU8G*_yQnP>1`*WDDE0=y2Pmiu*GGRk>2A+U^HAIII0O&jpKj2`b{~e zA0BS>Y9+89=MnGg5wBd~#9U3o2o*J zghu;VtL&;YmqW>V4pHEXss3w_o=p9ti7W?_RQE3XK**V#9(gVv_A?1@cRo4V$AM$s zxrwJ6)OX7VY}VA~`aMPjqoS^&O<3C;S=xQ#555UN9# zxCxH9mWeHO#DikyG7CUXEf57JylS9x~0`CS1z%1q-SIe~$L#ifVR?|f~}5%~6*b-cR{5Ht{F*=U6UF?U6~rxvRFQL{k(9_Pgd#DYrb2f@Q!GZsC!I@tN!zzc&nKjAH@KTP|?yZ096neC|zHG{Cb{Vbk%SA+ted8o}bG z+J1RxB5hC2Zo%B3JJ>yOZSIVQ8-Oc{uRp>xyI&jvU1=cCWah_rl9Dq_cUDN|3k85a zpqA}g}9)$BG#LxXaKa4_POkh$Ed@L=1CdM))%*zMp!JPtBB z%ytLT5 zGy!CAh_syiu!Dg>YbCyM2K8a@w4?Ub`74!VOm%tridw7b)^l8sF1%qoI9V~9Vn4T&B^M{{Il zI@yoaay5zA&KqTbtvY$EUO`90y=?&vY^RARs&R)5Hvt66Wkk*zUmLFDrB89i)E!Ef z!7;xWXufas11`TlDX=jw`Q{t8awwTaZq%TUw~v3^W(uVK$QncNU#w!ZhZ1uz#Tu2oz%0|8pWp~8n~weKNYwBz<|x=1oa6?(5v$%Rj`oBqal zdF)#wyIY$&LNQU_Duzgg_YDCD2B3ljf-r&vegXjiFoFbklkx>C6u`iM zdNjrvL5GF#$}k$O>vhUZOOr7MB!At@3ad)(m?EZ|vP!*F9)s5Ubv$;Z!jaDl;ON5;3P(1!Sqos=}YLW-zN+2xJL|k5+}UXr*LVEj=(7 zM-94sMmKDTK2z*PqqAQ3wW2V#W70>wl5Wn;+X=6H-R3_c1f?YWrk|tm>Ra$PzDshp zDLK%!`?vjMtrz}>VFv4OMt`SMWvr1*LW4}FWel7^Y&KxevN10a-)p|67qGoDy={-w zD*mY7Q7Bp6@=$r05pEMkM<%E_-OD0}D4zEi(sbH-;Fc;#x|$T23=un4J6(JilMeMO zzDc=G+X81LmuwcsDfSX!;(fn{y_h2-a}S2xr9}^j2Qe{cRb=Cvnt!W&>-)dxXa7pB za`c!wNzBe8`b=Ke#c=Y^Ji^LCu z;Wq*=l1=1BE>k{P5`TShaI-+NCE|{(UZ>S35{k{{n<58TwWA_SMBZODOsP;?4sQVwz|t(vcIDE5y0$a`^x@`}Bh{5F zVw=DiG}0W0 zW46vcWMXbn9e;u*_I4!48{9^is!t-IEp$n!GYTpCjoEz?adI%`9c%k(D;m3VuzXLX z!`GB?oobJofomMywO7mgZ9F{(Z{o6gjOKGE!@-x^U1RTML1NC9O71OfpC z00bc0b$m^CtpEJ59ge$#(%A+%4SarkZcT6vnmTTn8^nMF6pz3Pn@pqKm Date: Wed, 19 Feb 2025 20:54:40 +0900 Subject: [PATCH 5/6] =?UTF-8?q?[REFACTOR]=20}=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/umc7th/bulk/user/domain/User.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/umc7th/bulk/user/domain/User.java b/src/main/java/umc7th/bulk/user/domain/User.java index f5a5698..811abd1 100644 --- a/src/main/java/umc7th/bulk/user/domain/User.java +++ b/src/main/java/umc7th/bulk/user/domain/User.java @@ -174,6 +174,7 @@ public void markRecordComplete() { this.recordComplete = true; } + } public void updateCurrentNutrients(Long calories, Long carbos, Long proteins, Long fats) { this.curCalories += calories; this.curCarbos += carbos; From 68f278ef5c7ac675509aff3286f259650cbf732d Mon Sep 17 00:00:00 2001 From: eunsxx <88652027+eunsxx@users.noreply.github.com> Date: Wed, 19 Feb 2025 21:27:26 +0900 Subject: [PATCH 6/6] =?UTF-8?q?[FIX]=20keystore=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/certificate.crt | 21 +++++++++++++++++++++ src/main/resources/keystore.p12 | Bin 2712 -> 2704 bytes src/main/resources/private.key | 28 ++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 src/main/resources/certificate.crt create mode 100644 src/main/resources/private.key diff --git a/src/main/resources/certificate.crt b/src/main/resources/certificate.crt new file mode 100644 index 0000000..e26eefa --- /dev/null +++ b/src/main/resources/certificate.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIUWrOnf2nFmTI+YEg8AiaSqry4HPswDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNTAyMTkxMjI2MjJaFw0yNjAy +MTkxMjI2MjJaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCowVmGzO1HRrd22gUE3U66jSaBN1I9Zw8Uo7o9fUch +gAvDZUEY7zWlhCwWvyXaaG6opVwBH/n8Hwm+x+BSAqhcBfZyP6Cn5wNeXEn69Hx/ +4uIR3lrKo8cFeSm6ukwDuEi/Rk8Yp4Sfruu1ErDLJx/daA5HS6ikA7oyZpfMJN7x +NOs3bmbyrPvgCqEty+sGa3/tXPv8ocRjt829stDBVsEjEa6F7VcRRchIqIswA63B +KxJUTKI59NsLznr1hRsIOInwjEXlUPF2KwMwva+Eb0cA3SoXh9fizLMOtJ6lW5as +Xucm+spSV8EpfPkWi+Bn3z7DRfydtKzr0oWVMMObjLtDAgMBAAGjUzBRMB0GA1Ud +DgQWBBQNFGQPkXx1xq+hg8NvMEFqJYwpKjAfBgNVHSMEGDAWgBQNFGQPkXx1xq+h +g8NvMEFqJYwpKjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCd +ntLw/fXZpmH8RZ5W/972iBE0w4ZzxsdoXAKcMQUOoQDsypQLf9ZuUYYf3zuvUEjT +Rc8PWSnB44UHBi0AgHFmjOED+ct2bLOopWEJQ7/hXcwg9a1hQu4XG78RSG6FmX7q +frOUGZLAcVV3Yr7hR8BwVny4S/Fuze2u/SnnbgH1Y0KDvDlhhOfYjNDdDmRb+thI +zfpvSDE9ojvC/PwT/1pXPoLBb/BkILOKEeASmHUgb4LI1D3+Ak2z0tpPUAKmI+/P +b9NVAtuCkR6UvvGhxYklAnAdJIfn5NzRS+DVzHq3CgrCGVKfaShjZJT7HNu3Qqe9 +ZZWG85U/eCbbl0FVRB5o +-----END CERTIFICATE----- diff --git a/src/main/resources/keystore.p12 b/src/main/resources/keystore.p12 index 5be5a47ecbf1a129be8cef0e472fe650874b37c0..57bff3e84e1d031f8ccddbdd8393130fd297065f 100644 GIT binary patch literal 2704 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 literal 2712 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