Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/main/java/org/runimo/runimo/common/response/PageData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.runimo.runimo.common.response;

import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class PageData<T> {

private List<T> items;
private PageInfo pagination;

public static <T> PageData<T> of(List<T> items, PageInfo pagination) {
return new PageData<>(items, pagination);
}
}
29 changes: 29 additions & 0 deletions src/main/java/org/runimo/runimo/common/response/PageInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.runimo.runimo.common.response;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.domain.Page;

@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class PageInfo {


private Long totalItems;
private Integer totalPages;
private Integer currentPage;
private Integer perPage;

public static PageInfo empty(Integer currentPage, Integer perPage) {
return new PageInfo(0L, 0, currentPage, perPage);
}


public static PageInfo of(Page<?> pages) {

return new PageInfo(pages.getTotalElements(), pages.getTotalPages(), pages.getNumber(), pages.getSize());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.runimo.runimo.common.response;

import lombok.Getter;
import lombok.NoArgsConstructor;
import org.runimo.runimo.exceptions.code.CustomResponseCode;

@Getter
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
public class SuccessPageResponse<T> extends Response {

private PageData<T> payload;

public SuccessPageResponse(boolean success, String message, String code,
PageData<T> payload) {
super(success, message, code);
this.payload = payload;
}

public SuccessPageResponse(boolean success, CustomResponseCode code,
PageData<T> payload) {
super(success, code);
this.payload = payload;
}

public static <T> SuccessPageResponse<T> of(final CustomResponseCode responseCode,
PageData<T> data) {
return new SuccessPageResponse<>(true, responseCode, data);
}

}
218 changes: 111 additions & 107 deletions src/main/java/org/runimo/runimo/records/controller/RecordController.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
import java.net.URI;
import java.time.LocalDate;
import lombok.RequiredArgsConstructor;
import org.runimo.runimo.common.response.SuccessPageResponse;
import org.runimo.runimo.common.response.SuccessResponse;
import org.runimo.runimo.records.controller.request.MyRecordPageRequest;
import org.runimo.runimo.records.controller.request.RecordSaveRequest;
import org.runimo.runimo.records.controller.request.RecordUpdateRequest;
import org.runimo.runimo.records.enums.RecordHttpResponse;
import org.runimo.runimo.records.service.dto.RecordSimpleView;
import org.runimo.runimo.records.service.dto.RecordSimpleViewResponse;
import org.runimo.runimo.records.service.dto.WeeklyRecordStatResponse;
import org.runimo.runimo.records.service.dto.WeeklyStatQuery;
Expand All @@ -29,6 +32,7 @@
import org.runimo.runimo.user.enums.UserHttpResponseCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -43,118 +47,118 @@
@RequiredArgsConstructor
public class RecordController {

private final RecordCreateUsecase recordCreateUsecase;
private final RecordUpdateUsecase recordUpdateUsecase;
private final RecordQueryUsecase recordQueryUsecase;
private final RecordCreateUsecase recordCreateUsecase;
private final RecordUpdateUsecase recordUpdateUsecase;
private final RecordQueryUsecase recordQueryUsecase;

@Operation(summary = "기록 저장", description = "기록을 저장합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "기록 저장 성공",
content = @Content(schema = @Schema(implementation = RecordSaveResponse.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
@ApiResponse(responseCode = "401", description = "인증 실패")
})
@PostMapping
public ResponseEntity<SuccessResponse<RecordSaveResponse>> saveRecord(
@RequestBody RecordSaveRequest request,
@UserId Long userId
) {
RecordSaveResponse response = recordCreateUsecase.execute(
RecordCreateCommand.from(request, userId));
return ResponseEntity.created(URI.create("/api/v1/records/" + response.savedId()))
.body(SuccessResponse.of(RecordHttpResponse.RECORD_SAVED, response));
}
@Operation(summary = "기록 저장", description = "기록을 저장합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "기록 저장 성공",
content = @Content(schema = @Schema(implementation = RecordSaveResponse.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
@ApiResponse(responseCode = "401", description = "인증 실패")
})
@PostMapping
public ResponseEntity<SuccessResponse<RecordSaveResponse>> saveRecord(
@RequestBody RecordSaveRequest request,
@UserId Long userId
) {
RecordSaveResponse response = recordCreateUsecase.execute(
RecordCreateCommand.from(request, userId));
return ResponseEntity.created(URI.create("/api/v1/records/" + response.savedId()))
.body(SuccessResponse.of(RecordHttpResponse.RECORD_SAVED, response));
}

@Operation(summary = "기록 조회", description = "기록을 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "기록 조회 성공",
content = @Content(schema = @Schema(implementation = RecordDetailViewResponse.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
@ApiResponse(responseCode = "401", description = "인증 실패")
})
@GetMapping("/{recordId}")
public ResponseEntity<SuccessResponse<RecordDetailViewResponse>> viewRecord(
@PathVariable String recordId
) {
RecordDetailViewResponse response = recordQueryUsecase.getRecordDetailView(recordId);
return ResponseEntity.ok(SuccessResponse.of(RecordHttpResponse.RECORD_FETCHED, response));
}
@Operation(summary = "기록 조회", description = "기록을 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "기록 조회 성공",
content = @Content(schema = @Schema(implementation = RecordDetailViewResponse.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
@ApiResponse(responseCode = "401", description = "인증 실패")
})
@GetMapping("/{recordId}")
public ResponseEntity<SuccessResponse<RecordDetailViewResponse>> viewRecord(
@PathVariable String recordId
) {
RecordDetailViewResponse response = recordQueryUsecase.getRecordDetailView(recordId);
return ResponseEntity.ok(SuccessResponse.of(RecordHttpResponse.RECORD_FETCHED, response));
}

@Operation(summary = "기록 수정", description = "기록을 수정합니다.")
@ApiResponses(
value = {
@ApiResponse(responseCode = "200", description = "기록 수정 성공"),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
@ApiResponse(responseCode = "401", description = "인증 실패")
}
)
@PatchMapping("/{recordId}")
public ResponseEntity<Void> updateRecord(
@RequestBody RecordUpdateRequest request,
@NotNull @PathVariable String recordId,
@UserId Long userId
) {
recordUpdateUsecase.updateRecord(RecordUpdateRequest.toCommand(userId, recordId, request));
return ResponseEntity.ok().build();
}
@Operation(summary = "기록 수정", description = "기록을 수정합니다.")
@ApiResponses(
value = {
@ApiResponse(responseCode = "200", description = "기록 수정 성공"),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
@ApiResponse(responseCode = "401", description = "인증 실패")
}
)
@PatchMapping("/{recordId}")
public ResponseEntity<Void> updateRecord(
@RequestBody RecordUpdateRequest request,
@NotNull @PathVariable String recordId,
@UserId Long userId
) {
recordUpdateUsecase.updateRecord(RecordUpdateRequest.toCommand(userId, recordId, request));
return ResponseEntity.ok().build();
}

@Operation(summary = "주간 기록 통계 조회", description = "요청한 기간의 주간 기록 통계를 조회")
@ApiResponses(
value = {
@ApiResponse(responseCode = "200", description = "주간 기록 통계 조회 성공",
content = @Content(schema = @Schema(implementation = WeeklyRecordStatResponse.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
@ApiResponse(responseCode = "401", description = "인증 실패")
}
)
@GetMapping("/stats/weekly")
public ResponseEntity<SuccessResponse<WeeklyRecordStatResponse>> queryWeeklyRecordStat(
@RequestParam LocalDate startDate,
@RequestParam LocalDate endDate,
@UserId Long userId) {
WeeklyRecordStatResponse response = recordQueryUsecase.getUserWeeklyRecordStat(
new WeeklyStatQuery(userId, startDate, endDate));
return ResponseEntity.ok(
SuccessResponse.of(UserHttpResponseCode.MY_PAGE_DATA_FETCHED, response));
}
@Operation(summary = "주간 기록 통계 조회", description = "요청한 기간의 주간 기록 통계를 조회")
@ApiResponses(
value = {
@ApiResponse(responseCode = "200", description = "주간 기록 통계 조회 성공",
content = @Content(schema = @Schema(implementation = WeeklyRecordStatResponse.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
@ApiResponse(responseCode = "401", description = "인증 실패")
}
)
@GetMapping("/stats/weekly")
public ResponseEntity<SuccessResponse<WeeklyRecordStatResponse>> queryWeeklyRecordStat(
@RequestParam LocalDate startDate,
@RequestParam LocalDate endDate,
@UserId Long userId) {
WeeklyRecordStatResponse response = recordQueryUsecase.getUserWeeklyRecordStat(
new WeeklyStatQuery(userId, startDate, endDate));
return ResponseEntity.ok(
SuccessResponse.of(UserHttpResponseCode.MY_PAGE_DATA_FETCHED, response));
}

@Operation(summary = "월간 기록 통계 조회", description = "요청한 기간의 월간 기록 통계를 조회")
@ApiResponses(
value = {
@ApiResponse(responseCode = "200", description = "월간 기록 통계 조회 성공",
content = @Content(schema = @Schema(implementation = WeeklyRecordStatResponse.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
@ApiResponse(responseCode = "401", description = "인증 실패")
}
)
@GetMapping("/stats/monthly")
public ResponseEntity<SuccessResponse<MonthlyRecordStatResponse>> queryMonthlyRecordStat(
@RequestParam int year,
@RequestParam int month,
@UserId Long userId) {
if (month < 1 || month > 12) {
throw new IllegalArgumentException("잘못된 월입니다.");
}
MonthlyRecordStatResponse response = recordQueryUsecase.getUserMonthlyRecordStat(
new MonthlyStatQuery(userId, year, month));
return ResponseEntity.ok(
SuccessResponse.of(UserHttpResponseCode.MY_PAGE_DATA_FETCHED, response));
@Operation(summary = "월간 기록 통계 조회", description = "요청한 기간의 월간 기록 통계를 조회")
@ApiResponses(
value = {
@ApiResponse(responseCode = "200", description = "월간 기록 통계 조회 성공",
content = @Content(schema = @Schema(implementation = WeeklyRecordStatResponse.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"),
@ApiResponse(responseCode = "401", description = "인증 실패")
}
)
@GetMapping("/stats/monthly")
public ResponseEntity<SuccessResponse<MonthlyRecordStatResponse>> queryMonthlyRecordStat(
@RequestParam int year,
@RequestParam int month,
@UserId Long userId) {
if (month < 1 || month > 12) {
throw new IllegalArgumentException("잘못된 월입니다.");
}
MonthlyRecordStatResponse response = recordQueryUsecase.getUserMonthlyRecordStat(
new MonthlyStatQuery(userId, year, month));
return ResponseEntity.ok(
SuccessResponse.of(UserHttpResponseCode.MY_PAGE_DATA_FETCHED, response));
}

@Operation(summary = "개인 기록 페이지네이션 전체 조회", description = "개인 기록 페이지네이션 조회")
@ApiResponse(responseCode = "200", description = "기록 조회 성공",
content = @Content(schema = @Schema(implementation = RecordSimpleViewResponse.class)))
@GetMapping("/me")
public ResponseEntity<SuccessResponse<RecordSimpleViewResponse>> getMyRecordList(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@UserId Long userId
) {
return ResponseEntity.ok(
SuccessResponse.of(
RecordHttpResponse.RECORD_FETCHED,
recordQueryUsecase.getUserRecordSimpleView(userId, page, size)
)
);
}
@Operation(summary = "개인 기록 페이지네이션 전체 조회", description = "개인 기록 페이지네이션 조회")
@ApiResponse(responseCode = "200", description = "기록 조회 성공",
content = @Content(schema = @Schema(implementation = RecordSimpleViewResponse.class)))
@GetMapping("/me")
public ResponseEntity<SuccessPageResponse<RecordSimpleView>> getMyRecordList(
@ModelAttribute MyRecordPageRequest request,
@UserId Long userId
) {
return ResponseEntity.ok(
SuccessPageResponse.of(
RecordHttpResponse.RECORD_FETCHED,
recordQueryUsecase.getUserRecordSimpleViewByMonth(
MyRecordPageRequest.toQuery(request, userId))
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.runimo.runimo.records.controller.request;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import java.time.LocalDate;
import lombok.Getter;
import lombok.Setter;
import org.runimo.runimo.records.service.dto.RecordQuery;

@Getter
@Setter
public class MyRecordPageRequest {

@Min(0)
private Integer page = 0;
@Min(1)
@Max(20)
private Integer size = 10;
private LocalDate startDate = LocalDate.now();
private LocalDate endDate = LocalDate.now();

public static RecordQuery toQuery(MyRecordPageRequest request, Long userId) {
return new RecordQuery(userId, request.getPage(), request.getSize(),
request.getStartDate(), request.getEndDate());
}
}
Loading