Skip to content

Commit daa7dd7

Browse files
authored
Merge pull request #130 from realBULK/feat/125
Feat/125
2 parents bab0646 + 68f278e commit daa7dd7

14 files changed

Lines changed: 326 additions & 2 deletions

File tree

src/main/java/umc7th/bulk/BulkApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
55
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
66
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
7+
import org.springframework.scheduling.annotation.EnableScheduling;
78

89
@SpringBootApplication
910
@EnableJpaAuditing
11+
@EnableScheduling
1012
public class BulkApplication {
1113

1214
public static void main(String[] args) {

src/main/java/umc7th/bulk/record/repository/RecordRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ public interface RecordRepository extends JpaRepository<Record, Long> {
2222
@Query("SELECT r FROM Record r WHERE r.user = :user AND r.date = :date")
2323
List<Record> findByUserAndDate(@Param("user") User user, @Param("date") LocalDate date);
2424

25+
boolean existsByUserAndDate(User user, LocalDate date);
2526
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package umc7th.bulk.record.service;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.scheduling.annotation.Scheduled;
6+
import org.springframework.stereotype.Service;
7+
import org.springframework.transaction.annotation.Transactional;
8+
import umc7th.bulk.user.repository.UserRepository;
9+
10+
@Slf4j
11+
@Service
12+
@RequiredArgsConstructor
13+
public class RecordCompleteResetService {
14+
15+
private final UserRepository userRepository;
16+
17+
/**
18+
* 매일 자정에 record_complete 값을 false로 초기화하는 배치 작업
19+
*/
20+
21+
@Transactional
22+
@Scheduled(cron = "0 0 0 * * ?")
23+
public void resetRecordComplete() {
24+
log.info("매일 자정 record_complete 값 초기화 시작...");
25+
int updatedCount = userRepository.resetRecordComplete();
26+
log.info("✅ 초기화 완료: {}명의 record_complete 값을 false로 변경", updatedCount);
27+
}
28+
}

src/main/java/umc7th/bulk/record/service/RecordServiceImpl.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
import lombok.extern.slf4j.Slf4j;
88
import org.springframework.stereotype.Service;
99
import org.springframework.transaction.annotation.Transactional;
10+
import umc7th.bulk.global.error.GeneralErrorCode;
11+
import umc7th.bulk.global.error.exception.CustomException;
12+
import umc7th.bulk.group.entity.Group;
13+
import umc7th.bulk.group.repository.GroupRepository;
1014
import umc7th.bulk.meal.entity.MealType;
1115
import umc7th.bulk.mealItem.entity.MealItem;
1216
import umc7th.bulk.mealMealItemMapping.entity.MealMealItemMapping;
@@ -19,6 +23,8 @@
1923
import umc7th.bulk.record.upload.S3Service;
2024
import umc7th.bulk.recordedFood.entity.RecordedFood;
2125
import umc7th.bulk.recordedFood.repository.RecordedFoodRepository;
26+
import umc7th.bulk.stageRecord.entity.StageRecord;
27+
import umc7th.bulk.stageRecord.repository.StageRecordRepository;
2228
import umc7th.bulk.user.domain.User;
2329
import umc7th.bulk.user.repository.UserRepository;
2430
import umc7th.bulk.user.service.UserService;
@@ -42,6 +48,9 @@ public class RecordServiceImpl implements RecordService {
4248
private final UserService userService;
4349
private final UserRepository userRepository;
4450

51+
private final StageRecordRepository stageRecordRepository;
52+
private final GroupRepository groupRepository;
53+
4554
@Transactional
4655
public RecordResponseDto createRecord(RecordRequestDto.Create requestDto) {
4756
// 사용자 조회
@@ -58,6 +67,10 @@ public RecordResponseDto createRecord(RecordRequestDto.Create requestDto) {
5867
throw new IllegalArgumentException("이미 해당 날짜와 끼니에 대한 기록이 존재합니다.");
5968
}
6069

70+
// 사용자의 해당 날짜 기록 확인
71+
boolean hasRecordToday = recordRepository.existsByUserAndDate(user, requestDto.getDate());
72+
73+
6174
// 사용자의 끼니(MealType)에 해당하는 식단 데이터 조회
6275
List<MealMealItemMapping> mealMappings = mealMealItemMappingRepository.findByMeal_LocalDateAndMeal_Type(
6376
requestDto.getDate(), requestDto.getMealType());
@@ -80,6 +93,14 @@ public RecordResponseDto createRecord(RecordRequestDto.Create requestDto) {
8093

8194
Record savedRecord = recordRepository.save(record);
8295

96+
// 하루에 한 번이라도 기록하면 record_complete = true 설정
97+
if (!hasRecordToday) {
98+
user.markRecordComplete();
99+
userRepository.save(user);
100+
}
101+
102+
checkAndAdvanceStage(user.getGroup());
103+
83104
// MealItem을 기반으로 RecordedFood 생성
84105
List<RecordedFood> recordedFoods = mealMappings.stream()
85106
.map(MealMealItemMapping::getMealItem)
@@ -158,6 +179,10 @@ public RecordResponseDto createNotFollowedRecord(RecordRequestDto.CreateNotFollo
158179
// MealType 변환
159180
MealType type = requestDto.getMealType();
160181

182+
// 사용자의 해당 날짜 기록 확인
183+
boolean hasRecordToday = recordRepository.existsByUserAndDate(user, requestDto.getDate());
184+
185+
161186
String uploadedImageUrl = null;
162187
String gptRawResponseString = null;
163188

@@ -262,6 +287,14 @@ public RecordResponseDto createNotFollowedRecord(RecordRequestDto.CreateNotFollo
262287
Record savedRecord = recordRepository.save(record);
263288
log.info("✅ Record 저장 완료: recordId={}", savedRecord.getId());
264289

290+
// 하루에 한 번이라도 기록하면 record_complete = true 설정
291+
if (!hasRecordToday) {
292+
user.markRecordComplete();
293+
userRepository.save(user);
294+
}
295+
296+
checkAndAdvanceStage(user.getGroup());
297+
265298
// Response 생성
266299
return RecordResponseDto.builder()
267300
.recordId(savedRecord.getId())
@@ -356,5 +389,41 @@ public RecordResponseDto.TodaySummary getTodayRecord(User user) {
356389
.build();
357390
}
358391

392+
public void checkAndAdvanceStage(Group group) {
393+
// 현재 그룹에서 recordComplete = true인 유저 수 확인
394+
int recordedCount = userRepository.countByGroupAndRecordCompleteTrue(group);
395+
396+
if (recordedCount >= 5) {
397+
advanceStage(group);
398+
}
399+
}
400+
401+
private void advanceStage(Group group) {
402+
// 현재 그룹의 가장 최신 스테이지 가져오기
403+
StageRecord currentStageRecord = stageRecordRepository
404+
.findTopByGroupOrderByStageNumberDesc(group)
405+
.orElseThrow(() -> new CustomException(GeneralErrorCode.GROUP_NOT_FOUND_404));
406+
407+
// 현재 스테이지 완료 처리
408+
currentStageRecord.completeStage();
409+
stageRecordRepository.save(currentStageRecord);
410+
411+
// 그룹의 현재 스테이지 증가
412+
group.advanceStage();
413+
groupRepository.save(group);
414+
415+
// 새로운 스테이지 기록 생성
416+
StageRecord newStageRecord = StageRecord.builder()
417+
.group(group)
418+
.stageNumber(group.getCurrentStage())
419+
.totalUsers((int) userRepository.countByGroup(group))
420+
.recordedUsers(0) // 새로운 스테이지이므로 기록된 사용자 0명부터 시작
421+
.isCompleted(false)
422+
.build();
423+
424+
stageRecordRepository.save(newStageRecord);
425+
}
426+
427+
359428

360429
}

src/main/java/umc7th/bulk/stageRecord/entity/StageRecord.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public void increaseRecordedUsers() {
5050
this.recordedUsers++;
5151
}
5252

53+
public void increaseTotalUsers() { this.totalUsers++; }
54+
5355
// 스테이지 완료 처리 로직
5456
public void completeStage() {
5557
this.isCompleted = true;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package umc7th.bulk.stageRecord.repository;
22

33
import org.springframework.data.jpa.repository.JpaRepository;
4+
import umc7th.bulk.group.entity.Group;
45
import umc7th.bulk.stageRecord.entity.StageRecord;
56

67
import java.util.List;
8+
import java.util.Optional;
79

810
public interface StageRecordRepository extends JpaRepository<StageRecord, Long> {
911
List<StageRecord> findByGroupGroupIdOrderByStageNumberAsc(Long groupId);
12+
13+
Optional<StageRecord> findTopByGroupOrderByStageNumberDesc(Group group);
1014
}

src/main/java/umc7th/bulk/user/domain/User.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public class User extends BaseTimeEntity {
7676
private String favoriteFood;
7777

7878
@Column(nullable = false, name = "record_complete")
79-
private boolean recordComplete;
79+
private boolean recordComplete = false;
8080

8181
@Column(nullable = false, name = "access_token")
8282
private String accessToken;
@@ -168,6 +168,13 @@ public void setGroup(Group group) {
168168
}
169169
}
170170

171+
172+
public void markRecordComplete() {
173+
if (!this.recordComplete) {
174+
this.recordComplete = true;
175+
}
176+
177+
}
171178
public void updateCurrentNutrients(Long calories, Long carbos, Long proteins, Long fats) {
172179
this.curCalories += calories;
173180
this.curCarbos += carbos;

src/main/java/umc7th/bulk/user/repository/UserRepository.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package umc7th.bulk.user.repository;
22

33
import org.springframework.data.jpa.repository.JpaRepository;
4+
import org.springframework.data.jpa.repository.Modifying;
5+
import org.springframework.data.jpa.repository.Query;
6+
import org.springframework.data.repository.query.Param;
7+
import org.springframework.transaction.annotation.Transactional;
8+
import umc7th.bulk.group.entity.Group;
49
import umc7th.bulk.user.domain.User;
510

611
import java.util.List;
@@ -14,4 +19,22 @@ public interface UserRepository extends JpaRepository<User,Long> {
1419
List<User> findByGroupGroupIdAndRecordCompleteTrue(Long groupId); // 해당 그룹 id 에서 오늘 기록 달성한 사용자 리스트
1520
Optional<User> findByKakaoId(String kakaoId);
1621
Optional<User> findByEmail(String email);
22+
23+
@Modifying
24+
@Transactional
25+
@Query("UPDATE User u SET u.recordComplete = false")
26+
int resetRecordComplete();
27+
28+
// 특정 그룹 기록 달성한 인원 수 조회 (오늘 기록 완료한 인원 수)
29+
@Query("SELECT COUNT(u) FROM User u WHERE u.group = :group AND u.recordComplete = true")
30+
int countByGroupAndRecordCompleteTrue(@Param("group") Group group);
31+
32+
// 특정 그룹 총 인원 수 조회
33+
@Query("SELECT COUNT(u) FROM User u WHERE u.group = :group")
34+
int countByGroup(@Param("group") Group group);
35+
36+
37+
38+
39+
1740
}

src/main/java/umc7th/bulk/user/service/command/UserCommandServiceImpl.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import umc7th.bulk.global.jwt.util.JwtProvider;
1010
import umc7th.bulk.group.entity.Group;
1111
import umc7th.bulk.group.repository.GroupRepository;
12+
import umc7th.bulk.stageRecord.entity.StageRecord;
13+
import umc7th.bulk.stageRecord.repository.StageRecordRepository;
1214
import umc7th.bulk.user.domain.User;
1315
import umc7th.bulk.user.dto.UserRequestDTO;
1416
import umc7th.bulk.user.dto.UserResponseDTO;
@@ -30,6 +32,7 @@ public class UserCommandServiceImpl implements UserCommandService {
3032
private final JwtProvider jwtProvider;
3133
private final BulkCharacterRepository bulkCharacterRepository;
3234
private final GroupRepository groupRepository;
35+
private final StageRecordRepository stageRecordRepository;
3336

3437
@Override
3538
public UserResponseDTO.UserTokenDTO signup(UserRequestDTO.SignupDTO dto) {
@@ -69,9 +72,26 @@ public UserResponseDTO.UserTokenDTO signup(UserRequestDTO.SignupDTO dto) {
6972
.currentStage(1)
7073
.endDate(LocalDateTime.now().plusDays(7)) // 그룹 종료일 7일 후 설정
7174
.build();
72-
return groupRepository.save(newGroup);
75+
groupRepository.save(newGroup);
76+
77+
StageRecord firstStage = StageRecord.builder()
78+
.group(newGroup)
79+
.stageNumber(1)
80+
.totalUsers(1)
81+
.recordedUsers(0)
82+
.isCompleted(false)
83+
.build();
84+
stageRecordRepository.save(firstStage);
85+
86+
return newGroup;
7387
});
7488

89+
if (!groupRepository.findGroupWithSpace().isPresent()) { // 기존 그룹인지 확인
90+
StageRecord latestStage = stageRecordRepository.findTopByGroupOrderByStageNumberDesc(group)
91+
.orElseThrow(() -> new RuntimeException("StageRecord not found for existing group."));
92+
latestStage.increaseTotalUsers();
93+
stageRecordRepository.save(latestStage);
94+
}
7595

7696

7797
// User 저장 (BulkCharacter 포함)

src/main/resources/certificate.crt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDazCCAlOgAwIBAgIUWrOnf2nFmTI+YEg8AiaSqry4HPswDQYJKoZIhvcNAQEL
3+
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
4+
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNTAyMTkxMjI2MjJaFw0yNjAy
5+
MTkxMjI2MjJaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
6+
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
7+
AQUAA4IBDwAwggEKAoIBAQCowVmGzO1HRrd22gUE3U66jSaBN1I9Zw8Uo7o9fUch
8+
gAvDZUEY7zWlhCwWvyXaaG6opVwBH/n8Hwm+x+BSAqhcBfZyP6Cn5wNeXEn69Hx/
9+
4uIR3lrKo8cFeSm6ukwDuEi/Rk8Yp4Sfruu1ErDLJx/daA5HS6ikA7oyZpfMJN7x
10+
NOs3bmbyrPvgCqEty+sGa3/tXPv8ocRjt829stDBVsEjEa6F7VcRRchIqIswA63B
11+
KxJUTKI59NsLznr1hRsIOInwjEXlUPF2KwMwva+Eb0cA3SoXh9fizLMOtJ6lW5as
12+
Xucm+spSV8EpfPkWi+Bn3z7DRfydtKzr0oWVMMObjLtDAgMBAAGjUzBRMB0GA1Ud
13+
DgQWBBQNFGQPkXx1xq+hg8NvMEFqJYwpKjAfBgNVHSMEGDAWgBQNFGQPkXx1xq+h
14+
g8NvMEFqJYwpKjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCd
15+
ntLw/fXZpmH8RZ5W/972iBE0w4ZzxsdoXAKcMQUOoQDsypQLf9ZuUYYf3zuvUEjT
16+
Rc8PWSnB44UHBi0AgHFmjOED+ct2bLOopWEJQ7/hXcwg9a1hQu4XG78RSG6FmX7q
17+
frOUGZLAcVV3Yr7hR8BwVny4S/Fuze2u/SnnbgH1Y0KDvDlhhOfYjNDdDmRb+thI
18+
zfpvSDE9ojvC/PwT/1pXPoLBb/BkILOKEeASmHUgb4LI1D3+Ak2z0tpPUAKmI+/P
19+
b9NVAtuCkR6UvvGhxYklAnAdJIfn5NzRS+DVzHq3CgrCGVKfaShjZJT7HNu3Qqe9
20+
ZZWG85U/eCbbl0FVRB5o
21+
-----END CERTIFICATE-----

0 commit comments

Comments
 (0)