Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
11 changes: 11 additions & 0 deletions src/main/java/org/sopt/app/application/stamp/ClapService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.Objects;

import java.util.Optional;
import org.sopt.app.common.exception.BadRequestException;
import org.sopt.app.common.exception.ForbiddenException;
import org.sopt.app.common.exception.NotFoundException;
Expand Down Expand Up @@ -55,6 +56,16 @@ public int addClap(Long userId, Long stampId, int increment) {
return applied;
}

public Optional<Clap> getClap(Long userId, Long stampId) {
return clapRepository.findByUserIdAndStampId(userId, stampId);
}

public int getUserClapCount(Long userId, Long stampId) {
Optional<Clap> clap = getClap(userId, stampId);

return clap.map(Clap::getClapCount).orElse(0);
}

/**
* Clap(유저별 1행) 업데이트.
* - 없으면 생성하고, 있으면 도메인 메서드로 상한(50) 컷팅
Expand Down
40 changes: 40 additions & 0 deletions src/main/java/org/sopt/app/application/stamp/StampInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.time.LocalDateTime;
import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -14,6 +15,7 @@ public class StampInfo {
@Getter
@Builder
@ToString
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public static class Stamp {

private Long id;
Expand All @@ -24,5 +26,43 @@ public static class Stamp {
private String activityDate;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private int clapCount;
private int viewCount;
}

@Getter
@Builder
@ToString
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public static class StampView {

private Long id;
private String contents;
private List<String> images;
private Long userId;
private Long missionId;
private String activityDate;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private int clapCount;
private int viewCount;
private boolean isMine;
private int myClapCount;

public static StampView of(Stamp stamp, int myClapCount, boolean isMine) {
return StampView.builder()
.id(stamp.getId())
.contents(stamp.getContents())
.images(stamp.getImages())
.activityDate(stamp.getActivityDate())
.createdAt(stamp.getCreatedAt())
.updatedAt(stamp.getUpdatedAt())
.missionId(stamp.getMissionId())
.clapCount(stamp.getClapCount())
.viewCount(stamp.getViewCount() + 1)
.isMine(isMine)
.myClapCount(myClapCount)
.build();
}
}
}
10 changes: 10 additions & 0 deletions src/main/java/org/sopt/app/application/stamp/StampService.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,15 @@ public StampInfo.Stamp findStamp(Long missionId, Long userId) {
entity.validate();
return StampInfo.Stamp.builder()
.id(entity.getId())
.userId(entity.getUserId())
.contents(entity.getContents())
.images(entity.getImages())
.activityDate(entity.getActivityDate())
.createdAt(entity.getCreatedAt())
.updatedAt(entity.getUpdatedAt())
.missionId(entity.getMissionId())
.clapCount(entity.getClapCount())
.viewCount(entity.getViewCount())
.build();
}

Expand Down Expand Up @@ -87,6 +90,8 @@ public StampInfo.Stamp uploadStamp(
.createdAt(newStamp.getCreatedAt())
.updatedAt(newStamp.getUpdatedAt())
.missionId(newStamp.getMissionId())
.clapCount(newStamp.getClapCount())
.viewCount(newStamp.getViewCount())
.build();
}

Expand Down Expand Up @@ -202,4 +207,9 @@ public int getStampClapCount(Long stampId) {
.orElseThrow(() -> new NotFoundException(ErrorCode.STAMP_NOT_FOUND))
.getClapCount();
}

@Transactional
public void increaseViewCountById(Long stampId) {
stampRepository.increaseViewCount(stampId);
}
}
15 changes: 4 additions & 11 deletions src/main/java/org/sopt/app/domain/entity/soptamp/Stamp.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
import org.sopt.app.domain.entity.BaseEntity;
import org.springframework.util.StringUtils;

@Builder
@Entity
@Getter
@Builder
@NoArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Stamp extends BaseEntity {

Expand All @@ -34,8 +34,10 @@ public class Stamp extends BaseEntity {
@Column(length = 10)
private String activityDate;

@Builder.Default
private int clapCount = 0;

@Builder.Default
private int viewCount = 0;

@Version
Expand Down Expand Up @@ -68,13 +70,4 @@ public void validate() {
}
}

public void incrementClapCount(int increment) {
if (increment <= 0) return;
this.clapCount += increment;
}

public void incrementViewCount() {
this.viewCount += 1;
}

}
24 changes: 18 additions & 6 deletions src/main/java/org/sopt/app/facade/SoptampFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,52 @@

import java.util.List;

import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.sopt.app.application.mission.MissionInfo.Level;
import org.sopt.app.application.mission.MissionService;
import org.sopt.app.application.soptamp.*;
import org.sopt.app.application.stamp.ClapService;
import org.sopt.app.application.stamp.StampInfo;
import org.sopt.app.application.stamp.StampInfo.Stamp;
import org.sopt.app.application.stamp.StampInfo.StampView;
import org.sopt.app.application.stamp.StampService;
import org.sopt.app.domain.entity.soptamp.Mission;
import org.sopt.app.presentation.rank.*;
import org.sopt.app.presentation.stamp.StampRequest;
import org.sopt.app.presentation.stamp.StampRequest.RegisterStampRequest;
import org.sopt.app.presentation.stamp.StampResponse;
import org.sopt.app.presentation.stamp.StampResponse.SoptampReportResponse;
import org.sopt.app.presentation.stamp.StampResponseMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class SoptampFacade {

private final StampService stampService;
private final MissionService missionService;
private final SoptampUserService soptampUserService;
private final RankResponseMapper rankResponseMapper;
private final SoptampUserFinder soptampUserFinder;
private final ClapService clapService;

private final RankResponseMapper rankResponseMapper;

@Value("${makers.app.soptamp.report.url}")
private String formUrl;

@Transactional
public Stamp uploadStamp(Long userId, RegisterStampRequest registerStampRequest){
public StampInfo.Stamp uploadStamp(Long userId, RegisterStampRequest registerStampRequest){
stampService.checkDuplicateStamp(userId, registerStampRequest.getMissionId());
Stamp result = stampService.uploadStamp(registerStampRequest, userId);
Level mission = missionService.getMissionById(registerStampRequest.getMissionId());
soptampUserService.addPointByLevel(userId, mission.getLevel());

return result;
}

Expand Down Expand Up @@ -70,9 +76,15 @@ public SoptampUserInfo editSoptampUserProfileMessage(Long userId, String newProf
return soptampUserService.editProfileMessage(userId, newProfileMessage);
}

public Stamp getStampInfo(Long missionId, String nickname){
val userId = soptampUserFinder.findByNickname(nickname).getUserId();
return stampService.findStamp(missionId, userId);
public StampInfo.StampView getStampInfo(Long requestUserId, Long missionId, String nickname){
val soptampUserId = soptampUserFinder.findByNickname(nickname).getUserId();
val stamp = stampService.findStamp(missionId, soptampUserId);
val requestUserClapCount = clapService.getUserClapCount(requestUserId, stamp.getId());

stampService.increaseViewCountById(stamp.getId());

return StampInfo.StampView.of(
stamp, requestUserClapCount, Objects.equals(requestUserId, soptampUserId));
Comment on lines +81 to +87
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 응답 매핑에 들어가는 stamp가 viewCount ++ 되기 전이라서 응답의 viewCount에 내 조회가 포함된 viewCount가 들어가지 않네요! 정합성이 엄청 중요한 필드는 아니니 증가 후 재조회할 필요까진 없을 것 같지만, 응답에서 viewCount + 1해서 내려주면 좋을 것 같아요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

원래 응답 Dto가 중복으로 사용되는 부분들이 있어서 이렇게 + 1 을 해주기 좀 애매하다고 생각했는데, 아예 view 라는 네이밍으로 조회 시 사용하는 Dto를 분리해버리고 viewCount 가 + 1 된 값으로 응답하도록 반영하겠습니다!

}

public RankResponse.Detail findSoptampUserAndCompletedMissionByNickname(String nickname) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import java.util.Optional;
import org.sopt.app.domain.entity.soptamp.Stamp;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface StampRepository extends JpaRepository<Stamp, Long>, StampRepositoryCustom {

Expand All @@ -15,4 +18,11 @@ public interface StampRepository extends JpaRepository<Stamp, Long>, StampReposi

Optional<Stamp> findByIdAndUserId(Long id, Long userId);

@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query("""
update Stamp s set s.viewCount = s.viewCount + 1
where s.id = :stampId
""")
void increaseViewCount(@Param("stampId") Long stampId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ public class StampController {
@ApiResponse(responseCode = "500", description = "server error", content = @Content)
})
@GetMapping("")
public ResponseEntity<StampResponse.StampMain> findStampByMissionAndUserId(
public ResponseEntity<StampResponse.StampView> findStampByMissionAndUserId(
@AuthenticationPrincipal Long userId,
@Valid @ModelAttribute StampRequest.FindStampRequest findStampRequest
) {
val result = soptampFacade.getStampInfo(findStampRequest.getMissionId(), findStampRequest.getNickname());
val response = stampResponseMapper.of(result);
val result = soptampFacade.getStampInfo(userId, findStampRequest.getMissionId(), findStampRequest.getNickname());
val response = stampResponseMapper.from(result);
return ResponseEntity.ok(response);
}

Expand All @@ -53,7 +54,7 @@ public ResponseEntity<StampResponse.StampMain> registerStamp(
@Valid @RequestBody StampRequest.RegisterStampRequest registerStampRequest
) {
val result = soptampFacade.uploadStamp(userId, registerStampRequest);
val response = stampResponseMapper.of(result);
val response = stampResponseMapper.from(result);
return ResponseEntity.ok(response);
}

Expand Down
36 changes: 36 additions & 0 deletions src/main/java/org/sopt/app/presentation/stamp/StampResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -14,6 +15,7 @@ public class StampResponse {
@Getter
@AllArgsConstructor(access = AccessLevel.PUBLIC)
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
public static class StampMain {

@Schema(description = "스탬프 아이디", example = "1")
Expand All @@ -30,6 +32,40 @@ public static class StampMain {
private LocalDateTime updatedAt;
@Schema(description = "미션 아이디", example = "3")
private Long missionId;
@Schema(description = "총 박수 횟수", example = "124")
private int clapCount;
@Schema(description = "조회수", example = "58")
private int viewCount;
}

@Getter
@AllArgsConstructor(access = AccessLevel.PUBLIC)
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
public static class StampView {

@Schema(description = "스탬프 아이디", example = "1")
private Long id;
@Schema(description = "스탬프 내용", example = "모각공했다!")
private String contents;
@Schema(description = "스탬프 이미지", example = "[https://s3.ap-northeast-2.amazonaws.com/example/283aab53-22e3-46da-85ec-146c99f82ed4.jpeg]")
private List<String> images;
@Schema(description = "활동 날짜", example = "2024.04.08")
private String activityDate;
@Schema(description = "스탬프 생성 일시", example = "2023-03-29T18:39:42.106369")
private LocalDateTime createdAt;
@Schema(description = "스탬프 수정 일시", example = "2023-03-29T18:39:42.106369")
private LocalDateTime updatedAt;
@Schema(description = "미션 아이디", example = "3")
private Long missionId;
@Schema(description = "총 박수 횟수", example = "124")
private int clapCount;
@Schema(description = "조회수", example = "58")
private int viewCount;
@Schema(description = "내 스탬프인지 여부", example = "false")
private boolean isMine;
@Schema(description = "해당 스탬프에 대한 내 박수 횟수", example = "33")
private int myClapCount;
}

@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,23 @@
)
public interface StampResponseMapper {

StampResponse.StampMain of(StampInfo.Stamp stamp);
StampResponse.StampMain from(StampInfo.Stamp stampInfo);

default StampResponse.StampView from(StampInfo.StampView stampView) {
return StampResponse.StampView.builder()
.id(stampView.getId())
.contents(stampView.getContents())
.images(stampView.getImages())
.activityDate(stampView.getActivityDate())
.createdAt(stampView.getCreatedAt())
.updatedAt(stampView.getUpdatedAt())
.missionId(stampView.getMissionId())
.clapCount(stampView.getClapCount())
.viewCount(stampView.getViewCount())
.myClapCount(stampView.getMyClapCount())
.isMine(stampView.isMine())
.build();
}

StampResponse.StampId of(Long stampId);

Expand Down