Skip to content

Commit 0f7f598

Browse files
authored
[DEV-6] 활동 보고서 회차별 기간 API (#58)
1 parent d31b449 commit 0f7f598

12 files changed

+212
-18
lines changed

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ dependencies {
4646
implementation 'io.sentry:sentry-logback:7.6.0'
4747
implementation 'org.springdoc:springdoc-openapi-ui:1.6.11'
4848

49+
implementation 'com.fasterxml.jackson.core:jackson-core:2.17.0'
50+
4951
compileOnly 'org.projectlombok:lombok'
5052
runtimeOnly 'com.h2database:h2'
5153
annotationProcessor 'org.projectlombok:lombok'

src/main/java/ddingdong/ddingdongBE/auth/PrincipalDetails.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ddingdong.ddingdongBE.auth;
22

33
import ddingdong.ddingdongBE.domain.user.entity.User;
4+
import io.swagger.v3.oas.annotations.Hidden;
45
import java.util.ArrayList;
56
import java.util.Collection;
67
import lombok.Getter;
@@ -9,6 +10,7 @@
910
import org.springframework.security.core.authority.SimpleGrantedAuthority;
1011
import org.springframework.security.core.userdetails.UserDetails;
1112

13+
@Hidden
1214
@RequiredArgsConstructor
1315
@Getter
1416
public class PrincipalDetails implements UserDetails {

src/main/java/ddingdong/ddingdongBE/common/exception/ExceptionController.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package ddingdong.ddingdongBE.common.exception;
22

3-
import static ddingdong.ddingdongBE.common.exception.ErrorMessage.*;
3+
import static ddingdong.ddingdongBE.common.exception.ErrorMessage.INTERNAL_SERVER_ERROR;
44

5+
import io.swagger.v3.oas.annotations.Hidden;
56
import java.util.NoSuchElementException;
67
import lombok.extern.slf4j.Slf4j;
78
import org.springframework.http.HttpStatus;
@@ -11,6 +12,7 @@
1112
import org.springframework.web.bind.annotation.RestControllerAdvice;
1213
import org.springframework.web.multipart.support.MissingServletRequestPartException;
1314

15+
@Hidden
1416
@RestControllerAdvice
1517
@Slf4j
1618
public class ExceptionController {

src/main/java/ddingdong/ddingdongBE/common/handler/RestAuthenticationEntryPoint.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package ddingdong.ddingdongBE.common.handler;
22

3-
import static ddingdong.ddingdongBE.common.exception.ErrorMessage.*;
3+
import static ddingdong.ddingdongBE.common.exception.ErrorMessage.INVALID_PASSWORD;
4+
import static ddingdong.ddingdongBE.common.exception.ErrorMessage.NON_VALIDATED_TOKEN;
5+
import static ddingdong.ddingdongBE.common.exception.ErrorMessage.valueOf;
46

57
import com.fasterxml.jackson.databind.ObjectMapper;
68
import ddingdong.ddingdongBE.common.exception.ErrorMessage;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package ddingdong.ddingdongBE.domain.activityreport.api;
2+
3+
import ddingdong.ddingdongBE.auth.PrincipalDetails;
4+
import ddingdong.ddingdongBE.domain.activityreport.controller.dto.request.CreateActivityTermInfoRequest;
5+
import ddingdong.ddingdongBE.domain.activityreport.controller.dto.response.ActivityReportTermInfoResponse;
6+
import ddingdong.ddingdongBE.domain.activityreport.controller.dto.response.AllActivityReportResponse;
7+
import io.swagger.v3.oas.annotations.Operation;
8+
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
9+
import io.swagger.v3.oas.annotations.tags.Tag;
10+
import java.util.List;
11+
import org.springframework.http.HttpStatus;
12+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
13+
import org.springframework.web.bind.annotation.GetMapping;
14+
import org.springframework.web.bind.annotation.PostMapping;
15+
import org.springframework.web.bind.annotation.RequestBody;
16+
import org.springframework.web.bind.annotation.RequestMapping;
17+
import org.springframework.web.bind.annotation.ResponseStatus;
18+
19+
@Tag(name = "Activity Report - Admin", description = "Activity Report Admin API")
20+
@RequestMapping("/server/admin/activity-reports")
21+
public interface AdminActivityReportApi {
22+
23+
@Operation(summary = "활동 보고서 전체 조회")
24+
@GetMapping
25+
@ResponseStatus(HttpStatus.OK)
26+
List<AllActivityReportResponse> getActivityReports();
27+
28+
@Operation(summary = "활동 보고서 회차별 기간 조회 API")
29+
@GetMapping("/term")
30+
@ResponseStatus(HttpStatus.OK)
31+
@SecurityRequirement(name = "AccessToken")
32+
List<ActivityReportTermInfoResponse> getActivityTermInfos(
33+
@AuthenticationPrincipal PrincipalDetails principalDetails);
34+
35+
@Operation(summary = "활동 보고서 회차별 기간 설정 API")
36+
@PostMapping("/term")
37+
@ResponseStatus(HttpStatus.CREATED)
38+
@SecurityRequirement(name = "AccessToken")
39+
void createActivityTermInfo(
40+
@AuthenticationPrincipal PrincipalDetails principalDetails,
41+
@RequestBody CreateActivityTermInfoRequest request
42+
);
43+
44+
}
Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,42 @@
11
package ddingdong.ddingdongBE.domain.activityreport.controller;
22

3+
import ddingdong.ddingdongBE.auth.PrincipalDetails;
4+
import ddingdong.ddingdongBE.domain.activityreport.api.AdminActivityReportApi;
5+
import ddingdong.ddingdongBE.domain.activityreport.controller.dto.request.CreateActivityTermInfoRequest;
6+
import ddingdong.ddingdongBE.domain.activityreport.controller.dto.response.ActivityReportTermInfoResponse;
37
import ddingdong.ddingdongBE.domain.activityreport.controller.dto.response.AllActivityReportResponse;
48
import ddingdong.ddingdongBE.domain.activityreport.service.ActivityReportService;
9+
import ddingdong.ddingdongBE.domain.activityreport.service.ActivityReportTermInfoService;
510
import java.util.List;
6-
711
import lombok.RequiredArgsConstructor;
8-
12+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
913
import org.springframework.web.bind.annotation.GetMapping;
10-
import org.springframework.web.bind.annotation.RequestMapping;
1114
import org.springframework.web.bind.annotation.RestController;
1215

1316
@RestController
1417
@RequiredArgsConstructor
15-
@RequestMapping("/server/admin/activity-reports")
16-
public class AdminActivityReportApiController {
18+
public class AdminActivityReportApiController implements AdminActivityReportApi {
1719

1820
private final ActivityReportService activityReportService;
21+
private final ActivityReportTermInfoService activityReportTermInfoService;
1922

2023
@GetMapping
2124
public List<AllActivityReportResponse> getActivityReports() {
2225
return activityReportService.getAll();
2326
}
27+
28+
@Override
29+
public List<ActivityReportTermInfoResponse> getActivityTermInfos(
30+
@AuthenticationPrincipal PrincipalDetails principalDetails) {
31+
return activityReportTermInfoService.getAll();
32+
}
33+
34+
@Override
35+
public void createActivityTermInfo(
36+
@AuthenticationPrincipal PrincipalDetails principalDetails,
37+
CreateActivityTermInfoRequest request
38+
) {
39+
activityReportTermInfoService.create(request.startDate(), request.totalTermCount());
40+
}
41+
2442
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package ddingdong.ddingdongBE.domain.activityreport.controller.dto.request;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import java.time.LocalDate;
5+
import javax.validation.constraints.Pattern;
6+
import org.springframework.format.annotation.DateTimeFormat;
7+
8+
@Schema(
9+
name = "CreateActivityTermInfoRequest",
10+
description = "활동 보고서 회차 시작 기준일 설정 요청"
11+
)
12+
public record CreateActivityTermInfoRequest(
13+
@Schema(description = "활동 보고서 시작 일자", example = "2024-07-22")
14+
@DateTimeFormat(pattern = "yyyy-MM-dd")
15+
@Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$", message = "날짜는 yyyy-MM-dd 형식이어야 합니다.")
16+
LocalDate startDate,
17+
@Schema(description = "설정할 총 회차 수", example = "10 (=총 10회 설정)")
18+
int totalTermCount
19+
) {
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package ddingdong.ddingdongBE.domain.activityreport.controller.dto.response;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import java.time.LocalDate;
5+
6+
@Schema(
7+
name = "ActivityReportTermInfoResponse",
8+
description = "활동 보고서 회차 전체 조회 응답"
9+
)
10+
public record ActivityReportTermInfoResponse(
11+
@Schema(description = "회차")
12+
int term,
13+
@Schema(description = "시작 일자", example = "2024-07-22")
14+
LocalDate startDate,
15+
@Schema(description = "마감 일자", example = "2024-08-04")
16+
LocalDate endDate
17+
) {
18+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package ddingdong.ddingdongBE.domain.activityreport.domain;
2+
3+
import java.time.LocalDate;
4+
import javax.persistence.Column;
5+
import javax.persistence.Entity;
6+
import javax.persistence.GeneratedValue;
7+
import javax.persistence.GenerationType;
8+
import javax.persistence.Id;
9+
import lombok.AccessLevel;
10+
import lombok.Builder;
11+
import lombok.Getter;
12+
import lombok.NoArgsConstructor;
13+
14+
@Entity
15+
@Getter
16+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
17+
public class ActivityReportTermInfo {
18+
19+
@Id
20+
@GeneratedValue(strategy = GenerationType.IDENTITY)
21+
private Long id;
22+
23+
@Column(nullable = false)
24+
private int term;
25+
26+
@Column(nullable = false, columnDefinition = "DATE")
27+
private LocalDate startDate;
28+
29+
@Column(nullable = false, columnDefinition = "DATE")
30+
private LocalDate endDate;
31+
32+
@Builder
33+
public ActivityReportTermInfo(int term, LocalDate startDate, LocalDate endDate) {
34+
this.term = term;
35+
this.startDate = startDate;
36+
this.endDate = endDate;
37+
}
38+
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package ddingdong.ddingdongBE.domain.activityreport.repository;
2+
3+
import ddingdong.ddingdongBE.domain.activityreport.domain.ActivityReportTermInfo;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
public interface ActivityReportTermInfoRepository extends JpaRepository<ActivityReportTermInfo, Long> {
7+
}

src/main/java/ddingdong/ddingdongBE/domain/activityreport/service/ActivityReportService.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package ddingdong.ddingdongBE.domain.activityreport.service;
22

33
import static ddingdong.ddingdongBE.domain.fileinformation.entity.FileDomainCategory.ACTIVITY_REPORT;
4-
import static ddingdong.ddingdongBE.domain.fileinformation.entity.FileDomainCategory.CLUB_INTRODUCE;
54
import static ddingdong.ddingdongBE.domain.fileinformation.entity.FileTypeCategory.IMAGE;
65

76
import ddingdong.ddingdongBE.domain.activityreport.controller.dto.request.RegisterActivityReportRequest;
@@ -12,23 +11,17 @@
1211
import ddingdong.ddingdongBE.domain.activityreport.controller.dto.response.DetailActivityReportResponse;
1312
import ddingdong.ddingdongBE.domain.activityreport.domain.ActivityReport;
1413
import ddingdong.ddingdongBE.domain.activityreport.repository.ActivityReportRepository;
15-
1614
import ddingdong.ddingdongBE.domain.club.entity.Club;
1715
import ddingdong.ddingdongBE.domain.club.service.ClubService;
18-
import ddingdong.ddingdongBE.domain.fileinformation.entity.FileInformation;
1916
import ddingdong.ddingdongBE.domain.fileinformation.service.FileInformationService;
2017
import ddingdong.ddingdongBE.domain.user.entity.User;
21-
2218
import java.time.Duration;
2319
import java.time.LocalDate;
24-
2520
import java.util.List;
2621
import java.util.Map;
2722
import java.util.stream.Collectors;
2823
import java.util.stream.IntStream;
29-
3024
import lombok.RequiredArgsConstructor;
31-
3225
import org.springframework.stereotype.Service;
3326
import org.springframework.transaction.annotation.Transactional;
3427

@@ -56,7 +49,7 @@ public List<AllActivityReportResponse> getAll() {
5649

5750
@Transactional(readOnly = true)
5851
public List<AllActivityReportResponse> getMyActivityReports(final User user) {
59-
Club club = clubService.findClubByUserId(user.getId());
52+
Club club = clubService.getByUserId(user.getId());
6053

6154
List<ActivityReport> activityReports = activityReportRepository.findByClubName(
6255
club.getName());
@@ -80,7 +73,7 @@ public List<DetailActivityReportResponse> getActivityReport(final String term,
8073
public Long register(final User user,
8174
final RegisterActivityReportRequest registerActivityReportRequest) {
8275

83-
Club club = clubService.findClubByUserId(user.getId());
76+
Club club = clubService.getByUserId(user.getId());
8477
ActivityReport activityReport = registerActivityReportRequest.toEntity(club);
8578

8679
ActivityReport savedActivityReport = activityReportRepository.save(activityReport);
@@ -90,7 +83,7 @@ public Long register(final User user,
9083

9184
public List<ActivityReportDto> update(final User user, final String term,
9285
final List<UpdateActivityReportRequest> requests) {
93-
Club club = clubService.findClubByUserId(user.getId());
86+
Club club = clubService.getByUserId(user.getId());
9487

9588
List<ActivityReport> activityReports = activityReportRepository.findByClubNameAndTerm(
9689
club.getName(), term);
@@ -103,7 +96,7 @@ public List<ActivityReportDto> update(final User user, final String term,
10396
}
10497

10598
public List<ActivityReportDto> delete(final User user, final String term) {
106-
Club club = clubService.findClubByUserId(user.getId());
99+
Club club = clubService.getByUserId(user.getId());
107100

108101
List<ActivityReport> activityReports = activityReportRepository.findByClubNameAndTerm(
109102
club.getName(), term);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package ddingdong.ddingdongBE.domain.activityreport.service;
2+
3+
import ddingdong.ddingdongBE.domain.activityreport.controller.dto.response.ActivityReportTermInfoResponse;
4+
import ddingdong.ddingdongBE.domain.activityreport.domain.ActivityReportTermInfo;
5+
import ddingdong.ddingdongBE.domain.activityreport.repository.ActivityReportTermInfoRepository;
6+
import java.time.LocalDate;
7+
import java.util.List;
8+
import java.util.stream.Collectors;
9+
import java.util.stream.IntStream;
10+
import lombok.RequiredArgsConstructor;
11+
import org.springframework.stereotype.Service;
12+
13+
@Service
14+
@RequiredArgsConstructor
15+
public class ActivityReportTermInfoService {
16+
17+
private final ActivityReportTermInfoRepository activityReportTermInfoRepository;
18+
19+
public List<ActivityReportTermInfoResponse> getAll() {
20+
List<ActivityReportTermInfo> termInfos = activityReportTermInfoRepository.findAll();
21+
22+
return termInfos.stream()
23+
.map(termInfo -> new ActivityReportTermInfoResponse(
24+
termInfo.getTerm(),
25+
termInfo.getStartDate(),
26+
termInfo.getEndDate()
27+
))
28+
.toList();
29+
}
30+
31+
public void create(LocalDate startDate, int totalTermCount) {
32+
activityReportTermInfoRepository.saveAll(
33+
IntStream.range(0, totalTermCount)
34+
.mapToObj(i -> {
35+
LocalDate termStartDate = startDate.plusDays(i * 14L);
36+
LocalDate termEndDate = termStartDate.plusDays(13L);
37+
return ActivityReportTermInfo.builder()
38+
.term(i + 1)
39+
.startDate(termStartDate)
40+
.endDate(termEndDate)
41+
.build();
42+
})
43+
.collect(Collectors.toList())
44+
);
45+
}
46+
47+
}

0 commit comments

Comments
 (0)