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
@@ -0,0 +1,38 @@
package umc.th.juinjang.api.note.liked.controller;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import umc.th.juinjang.api.dto.ApiResponse;
import umc.th.juinjang.api.note.liked.service.LikedNoteCommandService;
import umc.th.juinjang.api.note.liked.service.response.LikedNoteDeleteResponse;
import umc.th.juinjang.api.note.liked.service.response.LikedNotePostResponse;
import umc.th.juinjang.domain.member.model.Member;

@RestController
@RequestMapping("/api/v2/shared-notes")
@RequiredArgsConstructor
public class LikedNoteController {

private final LikedNoteCommandService likedNoteCommandService;

@Operation(summary = "공유노트 좋아요 등록 API")
@PostMapping("/{sharedNoteId}/likes")
public ApiResponse<LikedNotePostResponse> createLikedNote(@AuthenticationPrincipal Member member,
@PathVariable("sharedNoteId") Long sharedNoteId) {
return ApiResponse.onSuccess(likedNoteCommandService.createLikedNote(member, sharedNoteId));
}

@Operation(summary = "공유노트 좋아요 취소 API")
@DeleteMapping("/{sharedNoteId}/likes")
public ApiResponse<LikedNoteDeleteResponse> deleteLikedNote(@AuthenticationPrincipal Member member,
@PathVariable("sharedNoteId") Long sharedNoteId) {
return ApiResponse.onSuccess(likedNoteCommandService.deleteLikedNote(member, sharedNoteId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package umc.th.juinjang.api.note.liked.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import umc.th.juinjang.api.note.liked.service.response.LikedNoteDeleteResponse;
import umc.th.juinjang.api.note.liked.service.response.LikedNotePostResponse;
import umc.th.juinjang.api.note.shared.service.SharedNoteFinder;
import umc.th.juinjang.api.note.shared.service.SharedNoteUpdater;
import umc.th.juinjang.domain.member.model.Member;
import umc.th.juinjang.domain.note.liked.model.LikedNote;
import umc.th.juinjang.domain.note.shared.model.SharedNote;

@Service
@RequiredArgsConstructor
public class LikedNoteCommandService {

private final LikedNoteUpdater likedNoteUpdater;
private final SharedNoteFinder sharedNoteFinder;
private final SharedNoteUpdater sharedNoteUpdater;
private final LikedNoteFinder likedNoteFinder;
private final LikedNoteDeleter likedNoteDeleter;

@Transactional
public LikedNotePostResponse createLikedNote(Member member, Long sharedNoteId) {
SharedNote sharedNote = sharedNoteFinder.getById(sharedNoteId);
LikedNote likedNote = LikedNote.create(member, sharedNote);

likedNoteUpdater.save(likedNote);
sharedNoteUpdater.incrementLikedCountById(sharedNoteId);

return new LikedNotePostResponse(sharedNoteFinder.getLikedNoteById(sharedNoteId));
}

@Transactional
public LikedNoteDeleteResponse deleteLikedNote(Member member, Long sharedNoteId) {
SharedNote sharedNote = sharedNoteFinder.getById(sharedNoteId);
LikedNote likedNote = likedNoteFinder.getByMemberAndSharedNote(member, sharedNote);

likedNoteDeleter.delete(likedNote);
sharedNoteUpdater.decrementLikedCountById(sharedNoteId);

return new LikedNoteDeleteResponse(sharedNoteFinder.getLikedNoteById(sharedNoteId));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package umc.th.juinjang.api.note.liked.service;

import org.springframework.stereotype.Component;

import lombok.RequiredArgsConstructor;
import umc.th.juinjang.domain.note.liked.model.LikedNote;
import umc.th.juinjang.domain.note.liked.model.repository.LikedNoteRepository;

@Component
@RequiredArgsConstructor
public class LikedNoteDeleter {

private final LikedNoteRepository likedNoteRepository;

void delete(LikedNote likedNote) {
likedNoteRepository.delete(likedNote);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import org.springframework.stereotype.Component;

import lombok.RequiredArgsConstructor;
import umc.th.juinjang.common.code.status.ErrorStatus;
import umc.th.juinjang.common.exception.handler.LikedNoteHandler;
import umc.th.juinjang.domain.member.model.Member;
import umc.th.juinjang.domain.note.liked.model.LikedNote;
import umc.th.juinjang.domain.note.liked.model.repository.LikedNoteRepository;
import umc.th.juinjang.domain.note.shared.model.SharedNote;

Expand All @@ -16,4 +19,9 @@ public class LikedNoteFinder {
public boolean existsByMemberAndSharedNote(Member member, SharedNote sharedNote) {
return likedNoteRepository.existsByMemberAndSharedNote(member, sharedNote);
}

public LikedNote getByMemberAndSharedNote(Member member, SharedNote sharedNote) {
return likedNoteRepository.findByMemberAndSharedNote(member, sharedNote)
.orElseThrow(() -> new LikedNoteHandler(ErrorStatus.LIKEDNOTE_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package umc.th.juinjang.api.note.liked.service;

import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Component;

import lombok.RequiredArgsConstructor;
import umc.th.juinjang.common.code.status.ErrorStatus;
import umc.th.juinjang.common.exception.handler.LikedNoteHandler;
import umc.th.juinjang.common.exception.handler.SharedNoteHandler;
import umc.th.juinjang.domain.member.model.Member;
import umc.th.juinjang.domain.note.liked.model.LikedNote;
import umc.th.juinjang.domain.note.liked.model.repository.LikedNoteRepository;

@Component
@RequiredArgsConstructor
public class LikedNoteUpdater {

private final LikedNoteRepository likedNoteRepository;

public void save(LikedNote likedNote) {
try {
likedNoteRepository.save(likedNote);
} catch (DataIntegrityViolationException e) {
throw new LikedNoteHandler(ErrorStatus.LIKEDNOTE_CONFLICT);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package umc.th.juinjang.api.note.liked.service.response;

public record LikedNoteDeleteResponse(Long count) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package umc.th.juinjang.api.note.liked.service.response;

public record LikedNotePostResponse(long count) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SharedNoteFinder {

private final SharedNoteRepository sharedNoteRepository;

SharedNote getById(Long id) {
public SharedNote getById(Long id) {
return sharedNoteRepository.findById(id)
.orElseThrow(() -> new SharedNoteHandler(ErrorStatus.SHAREDNOTE_NOT_FOUND));
}
Expand All @@ -29,4 +29,9 @@ SharedNote findByIdWithNoteAndAddress(Long id) {
Optional<SharedNote> findById(Long id) {
return sharedNoteRepository.findById(id);
}

public Long getLikedNoteById(Long id) {
return sharedNoteRepository.getLikeCountById(id);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,12 @@ public class SharedNoteUpdater {
void updateViewCount(long sharedNoteId, long addAmount) {
sharedNoteRepository.incrementViewCount(sharedNoteId, addAmount);
}

public void incrementLikedCountById(Long sharedNoteId) {
sharedNoteRepository.incrementLikedCountById(sharedNoteId);
}

public void decrementLikedCountById(Long sharedNoteId) {
sharedNoteRepository.decrementLikedCountById(sharedNoteId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public record SharedNoteGetResponse(
String price,
String monthlyRent,
boolean isLiked,
int likedCount,
Long likedCount,
String period,
String updatedAt,
Long viewCount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,14 @@ public enum ErrorStatus implements BaseErrorCode {
// PencilAccount alert
PENCIL_ACCOUNT_NOT_FOUND(HttpStatus.BAD_REQUEST, "ACCOUNT4000", "멤버에 해당하는 계좌가 존재하지 않습니다."),

SHAREDNOTE_NOT_FOUND(HttpStatus.BAD_REQUEST, "SHAREDNOTE4000", "해당하는 공유노트가 존재하지 않습니다."),
SHAREDNOTE_NOT_FOUND(HttpStatus.NOT_FOUND, "SHAREDNOTE4000", "해당하는 공유노트가 존재하지 않습니다."),
SHAREDNOTE_NOT_ENOUGH_PENCIL(HttpStatus.BAD_REQUEST, "SHAREDNOTE4001", "보유한 연필 수가 부족합니다."),
SHAREDNOTE_CONFLICT(HttpStatus.CONFLICT, "SHAREDNOTE4002", "이미 구매한 노트입니다."),
SHAREDNOTE_DEADLOCK(HttpStatus.LOCKED, "SHAREDNOTE4003", "잠시 후 다시 시도해주세요. 현재 다른 요청이 처리 중입니다.");
SHAREDNOTE_DEADLOCK(HttpStatus.LOCKED, "SHAREDNOTE4003", "잠시 후 다시 시도해주세요. 현재 다른 요청이 처리 중입니다."),

// LikedNote
LIKEDNOTE_CONFLICT(HttpStatus.CONFLICT, "LIKEDNOTE4000", "이미 좋아요한 노트입니다"),
LIKEDNOTE_NOT_FOUND(HttpStatus.NOT_FOUND, "LIKEDNOTE4001", "이미 취소했거나 좋아요한 적이 없습니다.");

private final HttpStatus httpStatus;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package umc.th.juinjang.common.exception.handler;

import umc.th.juinjang.common.code.BaseErrorCode;
import umc.th.juinjang.common.exception.GeneralException;

public class LikedNoteHandler extends GeneralException {
public LikedNoteHandler(BaseErrorCode code) {
super(code);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,25 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import umc.th.juinjang.domain.member.model.Member;
import umc.th.juinjang.domain.note.shared.model.SharedNote;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(uniqueConstraints = {
@UniqueConstraint(
columnNames = {
"member_id",
"shared_note_id"
}
)
})
@Entity
public class LikedNote {

Expand All @@ -30,5 +41,14 @@ public class LikedNote {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "shared_note_id", nullable = false)
private SharedNote sharedNote;


@Builder
private LikedNote(Member member, SharedNote sharedNote) {
this.member = member;
this.sharedNote = sharedNote;
}

public static LikedNote create(Member member, SharedNote sharedNote) {
return LikedNote.builder().member(member).sharedNote(sharedNote).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package umc.th.juinjang.domain.note.liked.model.repository;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

import umc.th.juinjang.domain.member.model.Member;
Expand All @@ -9,4 +11,6 @@
public interface LikedNoteRepository extends JpaRepository<LikedNote, Long> {

boolean existsByMemberAndSharedNote(Member member, SharedNote sharedNote);

Optional<LikedNote> findByMemberAndSharedNote(Member member, SharedNote sharedNote);
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public class SharedNote extends BaseEntity {
@Comment("임장 가격")
private Long price;

private int likeCount;
private Long likeCount;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "limjang_id", nullable = false, unique = true)
Expand All @@ -62,5 +62,9 @@ public class SharedNote extends BaseEntity {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", nullable = false)
private Member member;

public Long increaseLikedCount() {
return this.likeCount = (likeCount == null ? 1L : likeCount + 1);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,15 @@ public interface SharedNoteRepository extends JpaRepository<SharedNote, Long> {
@Modifying
@Query("UPDATE SharedNote s SET s.viewCount = COALESCE(s.viewCount, 0) + :addAmount WHERE s.sharedNoteId = :sharedNoteId")
void incrementViewCount(@Param("sharedNoteId") Long sharedNoteId, @Param("addAmount") Long addAmount);

@Modifying
@Query("UPDATE SharedNote sn SET sn.likeCount = sn.likeCount + 1 WHERE sn.sharedNoteId = :sharedNoteId")
void incrementLikedCountById(@Param("sharedNoteId") Long sharedNoteId);

@Query("SELECT sn.likeCount FROM SharedNote sn WHERE sn.sharedNoteId = :sharedNoteId")
Long getLikeCountById(@Param("sharedNoteId") Long sharedNoteId);

@Modifying
@Query("UPDATE SharedNote sn SET sn.likeCount = sn.likeCount - 1 WHERE sn.sharedNoteId = :sharedNoteId")
void decrementLikedCountById(@Param("sharedNoteId") Long sharedNoteId);
}