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
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import java.net.URI;
import java.time.LocalDate;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -90,9 +91,10 @@ public ResponseEntity<SuccessResponse<RecordDetailViewResponse>> viewRecord(
@PatchMapping("/{recordId}")
public ResponseEntity<Void> updateRecord(
@RequestBody RecordUpdateRequest request,
@NotNull @PathVariable String recordId,
@UserId Long userId
) {
recordUpdateUsecase.updateRecord(RecordUpdateRequest.toCommand(userId, request));
recordUpdateUsecase.updateRecord(RecordUpdateRequest.toCommand(userId, recordId, request));
return ResponseEntity.ok().build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,25 @@


import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import org.runimo.runimo.records.service.usecases.dtos.RecordUpdateCommand;

@Schema(description = "사용자 달리기 기록 수정 요청 DTO")
public record RecordUpdateRequest(
@Schema(description = "달리기 제목", example = "오늘의 달리기")
String title,
@Schema(description = "달리기 시작 시각", example = "2021-10-10T10:10:10")
LocalDateTime startedAt,
@Schema(description = "달리기 종료 시각", example = "2021-10-10T10:20:10")
LocalDateTime endAt,
@Schema(description = "달린 거리 (미터)", example = "10000")
Long totalDistanceInMeters,
@Schema(description = "평균 페이스 (밀리초)", example = "300000")
Long averagePaceInMilliSeconds
@Schema(description = "달리기 설명", example = "오늘은 올림픽 공원을 달렸어요")
String description,
@Schema(description = "대표 이미지 URL", example = "https://example.com/image.jpg")
String imgUrl
) {

public static RecordUpdateCommand toCommand(Long userId, RecordUpdateRequest request) {
public static RecordUpdateCommand toCommand(Long userId, String recordPublicId, RecordUpdateRequest request) {
return RecordUpdateCommand.builder()
.recordPublicId(recordPublicId)
.editorId(userId)
.title(request.title)
.startedAt(request.startedAt)
.endAt(request.endAt)
.totalDistanceInMeters(request.totalDistanceInMeters)
.averagePaceInMilliSeconds(request.averagePaceInMilliSeconds)
.description(request.description)
.imgUrl(request.imgUrl)
.build();
}
}
55 changes: 34 additions & 21 deletions src/main/java/org/runimo/runimo/records/domain/RunningRecord.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import jakarta.persistence.Convert;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.PrePersist;
import jakarta.persistence.Table;
import java.time.Duration;
import java.time.LocalDateTime;
Expand All @@ -30,6 +31,8 @@ public class RunningRecord extends BaseEntity {
private String recordPublicId;
private Long userId;
private String title;
private String description;
private String imgUrl;
private LocalDateTime startedAt;
private LocalDateTime endAt;
@Embedded
Expand All @@ -44,12 +47,22 @@ public class RunningRecord extends BaseEntity {
private List<SegmentPace> pacePerKm;

@Builder
public RunningRecord(Long userId, String title, LocalDateTime startedAt, LocalDateTime endAt,
Distance totalDistance, Pace averagePace, Boolean isRewarded, List<SegmentPace> pacePerKm) {
public RunningRecord(
Long userId,
String title,
String description,
String imgUrl,
LocalDateTime startedAt,
LocalDateTime endAt,
Distance totalDistance,
Pace averagePace,
Boolean isRewarded,
List<SegmentPace> pacePerKm) {
this.userId = userId;
this.title = title;
this.description = description;
this.imgUrl = imgUrl;
this.pacePerKm = pacePerKm;
this.recordPublicId = UUID.randomUUID().toString();
this.startedAt = startedAt;
this.endAt = endAt;
this.isRewarded = isRewarded;
Expand All @@ -58,26 +71,19 @@ public RunningRecord(Long userId, String title, LocalDateTime startedAt, LocalDa
setTitleIfNull();
}

public static RunningRecord withoutId(Long userId, String title, LocalDateTime startedAt,
LocalDateTime endAt, Distance totalDistance, Pace averagePace) {
return RunningRecord.builder()
.userId(userId)
.title(title)
.startedAt(startedAt)
.endAt(endAt)
.totalDistance(totalDistance)
.averagePace(averagePace)
.build();
public void updateTitle(Long editor, String title) {
validateEditor(editor);
this.title = title;
}

public void updateDescription(Long editor, String description) {
validateEditor(editor);
this.description = description;
}

public void update(RunningRecord updatedEntity) {
validateEditor(updatedEntity.userId);
this.title = updatedEntity.getTitle();
this.startedAt = updatedEntity.getStartedAt();
this.endAt = updatedEntity.getEndAt();
this.averagePace = updatedEntity.averagePace;
this.recordPublicId = updatedEntity.recordPublicId;
this.isRewarded = updatedEntity.isRewarded;
public void updateImageUrl(Long editor, String imgUrl) {
validateEditor(editor);
this.imgUrl = imgUrl;
}

public void reward(Long editorId) {
Expand All @@ -101,6 +107,13 @@ public Duration getRunningTime() {
return Duration.between(startedAt, endAt);
}

@PrePersist
public void generateRecordPublicId() {
if (recordPublicId == null) {
this.recordPublicId = UUID.randomUUID().toString();
}
}

private void setTitleIfNull() {
if (this.title != null) return;
this.title = DefaultTitle.fromTime(this.startedAt).getTitle();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@

import java.util.NoSuchElementException;
import lombok.RequiredArgsConstructor;
import org.runimo.runimo.common.scale.Distance;
import org.runimo.runimo.common.scale.Pace;
import org.runimo.runimo.records.domain.RunningRecord;
import org.runimo.runimo.records.repository.RecordRepository;
import org.runimo.runimo.records.service.usecases.dtos.RecordCreateCommand;
import org.runimo.runimo.records.service.usecases.dtos.RecordSaveResponse;
import org.runimo.runimo.records.service.usecases.dtos.RecordUpdateCommand;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -19,31 +16,23 @@ public class RecordCommandService {
private final RecordRepository recordRepository;

@Transactional
public RecordSaveResponse saveRecord(Long userId, RecordCreateCommand command) {
public RunningRecord saveRecord(Long userId, RecordCreateCommand command) {
RunningRecord runningRecord = mapToCreatedRunningRecord(userId, command);
recordRepository.save(runningRecord);
return new RecordSaveResponse(runningRecord.getId());
return recordRepository.save(runningRecord);
}

@Transactional
public void updateRecord(RecordUpdateCommand command) {
RunningRecord runningRecord = recordRepository.findByRecordPublicId(
command.recordPublicId())
.orElseThrow(NoSuchElementException::new);
runningRecord.update(mapToUpdateRecord(command));

runningRecord.updateTitle(command.editorId(), command.title());
runningRecord.updateDescription(command.editorId(), command.description());
runningRecord.updateImageUrl(command.editorId(), command.imgUrl());
recordRepository.save(runningRecord);
}

private RunningRecord mapToUpdateRecord(RecordUpdateCommand command) {
return RunningRecord.withoutId(
command.editorId(),
command.title(),
command.startedAt(),
command.endAt(),
new Distance(command.totalDistanceInMeters()),
new Pace(command.averagePaceInMilliSeconds())
);
}

private RunningRecord mapToCreatedRunningRecord(Long id, RecordCreateCommand command) {
return RunningRecord.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public RecordSaveResponse execute(RecordCreateCommand command) {
runimoService.updateRunimoStat(user.getMainRunimoId(), command.totalDistanceInMeters());
}

return commandService.saveRecord(user.getId(), command);
return new RecordSaveResponse(commandService.saveRecord(user.getId(), command).getRecordPublicId());
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
package org.runimo.runimo.records.service.usecases.dtos;

import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Builder;
import org.runimo.runimo.records.domain.RunningRecord;

@Schema(description = "기록 상세 정보")
@Builder
public record RecordDetailViewResponse(
Long recordId,
@Schema(description = "기록 ID", example = "UUID-String")
String recordId,
@Schema(description = "기록 제목")
String title,
@Schema(description = "기록 시작 시간")
LocalDateTime startedAt,
LocalDateTime endAt,
@Schema(description = "총 기록 시간 (초 단위)")
Long totalRunningTime,
@Schema(description = "평균 페이스 (밀리세컨드 단위)")
Long averagePace,
@Schema(description = "총 거리 (미터 단위)")
Long totalDistance,
@Schema(description = "구간 페이스 리스트")
List<SegmentPace> segmentPaceList,
@Schema(description = "기록 이미지 URL")
String imgUrl
) {

public static RecordDetailViewResponse from(RunningRecord runningRecord) {
public static RecordDetailViewResponse from(final RunningRecord runningRecord) {
return RecordDetailViewResponse.builder()
.recordId(runningRecord.getId())
.recordId(runningRecord.getRecordPublicId())
.title(runningRecord.getTitle())
.startedAt(runningRecord.getStartedAt())
.endAt(runningRecord.getEndAt())
.totalRunningTime(runningRecord.getRunningTime().getSeconds())
.averagePace(runningRecord.getAveragePace().getPaceInMilliSeconds())
.totalDistance(runningRecord.getTotalDistance().getAmount())
.segmentPaceList(runningRecord.getPacePerKm())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package org.runimo.runimo.records.service.usecases.dtos;

public record RecordSaveResponse(Long savedId
import io.swagger.v3.oas.annotations.media.Schema;

@Schema(description = "기록 저장 응답 DTO")
public record RecordSaveResponse(
@Schema(description = "저장된 기록 ID", example = "UUID-String")
String savedId
) {

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package org.runimo.runimo.records.service.usecases.dtos;

import java.time.LocalDateTime;
import jakarta.validation.constraints.NotEmpty;
import lombok.Builder;

@Builder
public record RecordUpdateCommand(
Long editorId,
String recordPublicId,
@NotEmpty Long editorId,
@NotEmpty String recordPublicId,
String title,
LocalDateTime startedAt,
LocalDateTime endAt,
Long totalDistanceInMeters,
Long averagePaceInMilliSeconds
String description,
String imgUrl
) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

@Schema(description = "리워드 클레임 요청 DTO")
public record RewardClaimRequest(
@Schema(description = "보상을 요청하는 달리기 기록 ID", example = "1") Long recordId
@Schema(description = "보상을 요청하는 달리기 기록 ID", example = "UUID-record-id") String recordId
) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class RewardService {

@Transactional
public RewardResponse claimReward(RewardClaimCommand command) {
RunningRecord runningRecord = recordFinder.findById(command.recordId())
RunningRecord runningRecord = recordFinder.findByPublicId(command.recordPublicId())
.orElseThrow(NoSuchElementException::new);
validateRecord(runningRecord);
Egg grantedEgg = rewardEgg(command);
Expand Down Expand Up @@ -61,7 +61,7 @@ private boolean validateRecordIsFirstRecordOfWeek(RewardClaimCommand command) {
log.info("유저 {}의 첫번째 달리기 기록이 없습니다.", command.userId());
return false;
}
if (!command.recordId().equals(firstRecordOfWeek.get().getId())) {
if (!command.recordPublicId().equals(firstRecordOfWeek.get().getRecordPublicId())) {
log.info("유저 {}의 첫번째 달리기 기록이 아닙니다.", command.userId());
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public record RewardClaimCommand(
Long userId,
Long recordId
String recordPublicId
) {

}
2 changes: 2 additions & 0 deletions src/main/resources/sql/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ CREATE TABLE `running_record`
`user_id` INTEGER NOT NULL,
`record_public_id` VARCHAR(255) NOT NULL,
`title` VARCHAR(255),
`description` VARCHAR(255),
`img_url` VARCHAR(255),
`started_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`end_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`total_distance` INTEGER,
Expand Down
Loading
Loading