-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WALWAL-145] missionrecord calendarview #52
Changes from all commits
593d703
dd9db91
2b5f8e2
63e7e7f
b3c7b68
fdac3c2
0b151bc
abc1c44
4d3a2ce
a8a0ad8
7c516aa
4957ec4
94b521c
25815e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,11 +7,21 @@ | |
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecord; | ||
import com.depromeet.stonebed.domain.missionRecord.domain.MissionStatus; | ||
import com.depromeet.stonebed.domain.missionRecord.dto.request.MissionRecordCreateRequest; | ||
import com.depromeet.stonebed.domain.missionRecord.dto.response.MissionRecordCalendarDto; | ||
import com.depromeet.stonebed.domain.missionRecord.dto.response.MissionRecordCalendarResponse; | ||
import com.depromeet.stonebed.domain.missionRecord.dto.response.MissionRecordCreateResponse; | ||
import com.depromeet.stonebed.global.error.ErrorCode; | ||
import com.depromeet.stonebed.global.error.exception.CustomException; | ||
import com.depromeet.stonebed.global.util.MemberUtil; | ||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.time.format.DateTimeFormatter; | ||
import java.time.format.DateTimeParseException; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.data.domain.PageRequest; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.data.domain.Sort; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
|
@@ -24,10 +34,13 @@ public class MissionRecordService { | |
private final MissionRecordRepository missionRecordRepository; | ||
private final MemberUtil memberUtil; | ||
|
||
private static final DateTimeFormatter DATE_FORMATTER = | ||
DateTimeFormatter.ofPattern("yyyy-MM-dd"); | ||
|
||
public MissionRecordCreateResponse completeMission(MissionRecordCreateRequest request) { | ||
Mission mission = findMissionById(request.missionId()); | ||
|
||
Member member = memberUtil.getCurrentMember(); | ||
final Member member = memberUtil.getCurrentMember(); | ||
|
||
MissionRecord missionRecord = | ||
MissionRecord.builder() | ||
|
@@ -50,10 +63,50 @@ public void deleteMissionRecord(Long recordId) { | |
missionRecordRepository.delete(missionRecord); | ||
} | ||
|
||
// ๋จ์ผ ๋ฏธ์ ์กฐํ ๋ฉ์๋ | ||
private Mission findMissionById(Long missionId) { | ||
return missionRepository | ||
.findById(missionId) | ||
.orElseThrow(() -> new CustomException(ErrorCode.MISSION_NOT_FOUND)); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public MissionRecordCalendarResponse getMissionRecordsForCalendar(String cursor, int limit) { | ||
final Member member = memberUtil.getCurrentMember(); | ||
Pageable pageable = PageRequest.of(0, limit, Sort.by(Sort.Direction.ASC, "createdAt")); | ||
|
||
List<MissionRecord> records = getMissionRecords(cursor, member, pageable); | ||
|
||
List<MissionRecordCalendarDto> calendarData = | ||
records.stream() | ||
.map(record -> MissionRecordCalendarDto.from(record, DATE_FORMATTER)) | ||
.toList(); | ||
|
||
String nextCursor = getNextCursor(records); | ||
|
||
return MissionRecordCalendarResponse.from(calendarData, nextCursor); | ||
} | ||
|
||
private List<MissionRecord> getMissionRecords(String cursor, Member member, Pageable pageable) { | ||
if (cursor == null) { | ||
return missionRecordRepository.findByMemberIdWithPagination(member.getId(), pageable); | ||
} | ||
|
||
try { | ||
LocalDateTime cursorDate = LocalDate.parse(cursor, DATE_FORMATTER).atStartOfDay(); | ||
return missionRecordRepository.findByMemberIdAndCreatedAtFromWithPagination( | ||
member.getId(), cursorDate, pageable); | ||
} catch (DateTimeParseException e) { | ||
throw new CustomException(ErrorCode.INVALID_CURSOR_DATE_FORMAT); | ||
} | ||
} | ||
|
||
private String getNextCursor(List<MissionRecord> records) { | ||
if (records.isEmpty()) { | ||
return null; | ||
} | ||
|
||
MissionRecord lastRecord = records.get(records.size() - 1); | ||
LocalDate nextCursorDate = lastRecord.getCreatedAt().toLocalDate().plusDays(1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (์๊ฒฌ) ํ๋ ์ฐ๋ ค๊ฐ ๋๋ ์ ์ ์ฌ๊ธฐ์ plus 1์ ํ๊ฒ ๋๋ฉด ์๋ฅผ ๋ค์ด,
์ด๋ ๊ฒ 5๊ฐ์ ๋ ์ง๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๋ฉด ์์ฒญ์ cursor = null, limit = 2 ๋ก ํ๋ฉด ์ด๋ ๊ฒ ๋ ํ ๋ฐ ๊ทธ ๋ค์ ์์ฒญ ๋ 20240103์ผ๋ก ๋ณด๋ด๋ฉด ๋ญ๊ฐ ์ ๊ฐ ์ ๋ฒ์ ์ค๋ช
ํ์ ๋ +1์ผ๋ก ํ์ ์ด๋ฌ๋ ๊ฒ ๊ฐ์๋ฐ ๊ทผ๋ฐ ์ญ์ ์ ๊ฐ ์ฝ๋์ ๋ํ ์ดํด๊ฐ ๋ถ์กฑํด์ ํ๋ฆด ์๋ ์์ด์ ๊ทธ๋ฅ ์๊ฒฌ ์ ๋๋ก๋ง ์๊ฐํด์ฃผ์ธ์ ใ ใ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ์ค ์ข์ ์๊ฒฌ ๊ณ ๋ง์ CreatedAtAfter๋์ CreatedAtFrom์ผ๋ก ํฌํจํด์ ๋ณด๋ด์ฃผ๋ ๊ฑธ๋ก ๋ฐ๊ฟ๊ฒ!! |
||
return nextCursorDate.format(DATE_FORMATTER); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.depromeet.stonebed.domain.missionRecord.dao; | ||
|
||
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecord; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import org.springframework.data.domain.Pageable; | ||
|
||
public interface MissionRecordRepositoryCustom { | ||
List<MissionRecord> findByMemberIdWithPagination(Long memberId, Pageable pageable); | ||
|
||
List<MissionRecord> findByMemberIdAndCreatedAtFromWithPagination( | ||
Long memberId, LocalDateTime createdAt, Pageable pageable); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package com.depromeet.stonebed.domain.missionRecord.dao; | ||
|
||
import static com.depromeet.stonebed.domain.missionRecord.domain.QMissionRecord.missionRecord; | ||
|
||
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecord; | ||
import com.querydsl.core.types.dsl.BooleanExpression; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
@RequiredArgsConstructor | ||
public class MissionRecordRepositoryImpl implements MissionRecordRepositoryCustom { | ||
|
||
private final JPAQueryFactory queryFactory; | ||
|
||
@Override | ||
public List<MissionRecord> findByMemberIdWithPagination(Long memberId, Pageable pageable) { | ||
return queryFactory | ||
.selectFrom(missionRecord) | ||
.where(isMemberId(memberId)) | ||
.orderBy(missionRecord.createdAt.asc()) | ||
.offset(pageable.getOffset()) | ||
.limit(pageable.getPageSize()) | ||
.fetch(); | ||
} | ||
|
||
@Override | ||
public List<MissionRecord> findByMemberIdAndCreatedAtFromWithPagination( | ||
Long memberId, LocalDateTime createdAt, Pageable pageable) { | ||
return queryFactory | ||
.selectFrom(missionRecord) | ||
.where(missionRecord.member.id.eq(memberId).and(createdAtFrom(createdAt))) | ||
.orderBy(missionRecord.createdAt.asc()) | ||
.offset(pageable.getOffset()) | ||
.limit(pageable.getPageSize()) | ||
.fetch(); | ||
} | ||
|
||
private BooleanExpression isMemberId(Long memberId) { | ||
return missionRecord.member.id.eq(memberId); | ||
} | ||
|
||
private BooleanExpression createdAtFrom(LocalDateTime createdAt) { | ||
return missionRecord.createdAt.goe(createdAt); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.depromeet.stonebed.domain.missionRecord.dto.request; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import jakarta.validation.constraints.Min; | ||
import jakarta.validation.constraints.NotNull; | ||
|
||
public record MissionRecordCalendarRequest( | ||
@Schema(description = "์ปค์ ์์น", example = "2024-01-01") String cursor, | ||
@NotNull @Min(1) @Schema(description = "ํ์ด์ง ๋น ํญ๋ชฉ ์", example = "30") int limit) {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.depromeet.stonebed.domain.missionRecord.dto.response; | ||
|
||
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecord; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import java.time.format.DateTimeFormatter; | ||
|
||
public record MissionRecordCalendarDto( | ||
@Schema(description = "์ด๋ฏธ์ง ID") Long imageId, | ||
@Schema(description = "์ด๋ฏธ์ง URL") String imageUrl, | ||
@Schema(description = "๋ฏธ์ ์ํ ์ผ์") String missionDate) { | ||
|
||
public static MissionRecordCalendarDto from( | ||
MissionRecord missionRecord, DateTimeFormatter formatter) { | ||
String formattedDate = missionRecord.getCreatedAt().format(formatter); | ||
return new MissionRecordCalendarDto( | ||
missionRecord.getId(), missionRecord.getImageUrl(), formattedDate); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.depromeet.stonebed.domain.missionRecord.dto.response; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import java.util.List; | ||
|
||
public record MissionRecordCalendarResponse( | ||
@Schema( | ||
description = "๋ฏธ์ ๊ธฐ๋ก ๋ฐ์ดํฐ ๋ฆฌ์คํธ", | ||
example = | ||
"[{ 'imageId': 1, 'imageUrl': 'http://example.com/image1.jpg', 'missionDate': '2024-01-01' }]") | ||
List<MissionRecordCalendarDto> list, | ||
@Schema(description = "์ปค์ ์์น", example = "2024-01-03") String nextCursor) { | ||
|
||
public static MissionRecordCalendarResponse from( | ||
List<MissionRecordCalendarDto> list, String nextCursor) { | ||
return new MissionRecordCalendarResponse(list, nextCursor); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ ์ ๋ณ์ ์ ์ธ ์ข์์ฉ ๐