diff --git a/src/main/java/com/cabin/plat/domain/track/controller/TrackController.java b/src/main/java/com/cabin/plat/domain/track/controller/TrackController.java index 22eaa57..4a994f9 100644 --- a/src/main/java/com/cabin/plat/domain/track/controller/TrackController.java +++ b/src/main/java/com/cabin/plat/domain/track/controller/TrackController.java @@ -70,6 +70,14 @@ public BaseResponse getTrackFeeds( return BaseResponse.onSuccess(trackService.getTrackFeeds(member, page, size)); } + @Operation(summary = "트랙 삭제", description = "트랙을 삭제한다.") + @DeleteMapping("/{trackId}") + public BaseResponse deleteTrack( + @AuthMember Member member, + @PathVariable("trackId") Long trackId) { + return BaseResponse.onSuccess(trackService.deleteTrack(member, trackId)); + } + @Operation(summary = "트랙 신고", description = "트랙을 신고한다.") @PostMapping("/{trackId}/report") public BaseResponse reportTrack(@AuthMember Member member, @PathVariable("trackId") Long trackId) { diff --git a/src/main/java/com/cabin/plat/domain/track/entity/Track.java b/src/main/java/com/cabin/plat/domain/track/entity/Track.java index fd4c639..8fad225 100644 --- a/src/main/java/com/cabin/plat/domain/track/entity/Track.java +++ b/src/main/java/com/cabin/plat/domain/track/entity/Track.java @@ -4,12 +4,14 @@ import com.cabin.plat.global.common.BaseEntity; import jakarta.persistence.*; import lombok.*; +import org.hibernate.annotations.SQLRestriction; @Getter @Builder @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor +@SQLRestriction("deleted_at is null") public class Track extends BaseEntity { @Id diff --git a/src/main/java/com/cabin/plat/domain/track/service/TrackService.java b/src/main/java/com/cabin/plat/domain/track/service/TrackService.java index 9864634..f04a9bd 100644 --- a/src/main/java/com/cabin/plat/domain/track/service/TrackService.java +++ b/src/main/java/com/cabin/plat/domain/track/service/TrackService.java @@ -21,5 +21,7 @@ TrackResponse.TrackMapList getTracksByLocation( TrackResponse.TrackDetailList getTrackFeeds(Member member, int page, int size); + TrackResponse.TrackId deleteTrack(Member member, Long trackId); + TrackResponse.ReportId reportTrack(Member member, Long trackId); } diff --git a/src/main/java/com/cabin/plat/domain/track/service/TrackServiceImpl.java b/src/main/java/com/cabin/plat/domain/track/service/TrackServiceImpl.java index 9892457..994c048 100644 --- a/src/main/java/com/cabin/plat/domain/track/service/TrackServiceImpl.java +++ b/src/main/java/com/cabin/plat/domain/track/service/TrackServiceImpl.java @@ -4,6 +4,7 @@ import com.cabin.plat.domain.track.dto.TrackRequest; import com.cabin.plat.domain.track.dto.TrackResponse; import com.cabin.plat.domain.track.dto.TrackResponse.TrackDetail; +import com.cabin.plat.domain.track.dto.TrackResponse.TrackId; import com.cabin.plat.domain.track.entity.*; import com.cabin.plat.domain.track.mapper.TrackMapper; import com.cabin.plat.domain.track.repository.*; @@ -65,8 +66,7 @@ public TrackResponse.TrackMapList getTracksByLocation( @Override public TrackResponse.TrackDetail getTrackById(Member member, Long trackId) { - Track track = trackRepository.findById(trackId) - .orElseThrow(() -> new RestApiException(TrackErrorCode.TRACK_NOT_FOUND)); + Track track = findTrackById(trackId); return getTrackDetail(member, track); } @@ -74,8 +74,7 @@ public TrackResponse.TrackDetail getTrackById(Member member, Long trackId) { @Transactional @Override public TrackResponse.TrackId likeTrack(Member member, Long trackId, Boolean isLiked) { - Track track = trackRepository.findById(trackId) - .orElseThrow(() -> new RestApiException(TrackErrorCode.TRACK_NOT_FOUND)); + Track track = findTrackById(trackId); Optional existingLike = trackLikeRepository.findByMemberAndTrack(member, track); @@ -125,6 +124,31 @@ public TrackResponse.TrackDetailList getTrackFeeds(Member member, int page, int return trackMapper.toTrackDetailList(trackDetails); } + @Override + @Transactional + public TrackId deleteTrack(Member member, Long trackId) { + Track track = findTrackById(trackId); + Long trackUploaderId = track.getMember().getId(); + Long memberId = member.getId(); + if (!trackUploaderId.equals(memberId)) { + throw new RestApiException(TrackErrorCode.TRACK_DELETE_FORBIDDEN); + } + track.delete(); + return trackMapper.toTrackId(track.getId()); + } + + @Transactional + @Override + public TrackResponse.ReportId reportTrack(Member member, Long trackId) { + findTrackById(trackId); + + TrackReport trackReport = trackMapper.toTrackReport(trackId, member.getId()); + + TrackReport savedTrackReport = trackReportRepository.save(trackReport); + + return trackMapper.toReportId(savedTrackReport.getId()); + } + private TrackDetail getTrackDetail(Member member, Track track) { TrackResponse.MemberInfo memberInfo = trackMapper.toMemberInfo( track.getMember().getId(), @@ -148,16 +172,8 @@ private TrackDetail getTrackDetail(Member member, Track track) { ); } - @Transactional - @Override - public TrackResponse.ReportId reportTrack(Member member, Long trackId) { - trackRepository.findById(trackId) + private Track findTrackById(Long trackId) { + return trackRepository.findById(trackId) .orElseThrow(() -> new RestApiException(TrackErrorCode.TRACK_NOT_FOUND)); - - TrackReport trackReport = trackMapper.toTrackReport(trackId, member.getId()); - - TrackReport savedTrackReport = trackReportRepository.save(trackReport); - - return trackMapper.toReportId(savedTrackReport.getId()); } } diff --git a/src/main/java/com/cabin/plat/global/exception/errorCode/TrackErrorCode.java b/src/main/java/com/cabin/plat/global/exception/errorCode/TrackErrorCode.java index f50a5f0..a0f0da9 100644 --- a/src/main/java/com/cabin/plat/global/exception/errorCode/TrackErrorCode.java +++ b/src/main/java/com/cabin/plat/global/exception/errorCode/TrackErrorCode.java @@ -10,7 +10,8 @@ @AllArgsConstructor public enum TrackErrorCode implements ErrorCodeInterface { - TRACK_NOT_FOUND("TRACK001", "Track가 존재하지 않습니다.", HttpStatus.NOT_FOUND), + TRACK_NOT_FOUND("TRACK001", "Track이 존재하지 않습니다.", HttpStatus.NOT_FOUND), + TRACK_DELETE_FORBIDDEN("TRACK002", "이 트랙을 삭제할 권한이 없습니다.", HttpStatus.FORBIDDEN), ; private final String code; diff --git a/src/test/java/com/cabin/plat/domain/track/service/TrackServiceTest.java b/src/test/java/com/cabin/plat/domain/track/service/TrackServiceTest.java index 502fa40..814009f 100644 --- a/src/test/java/com/cabin/plat/domain/track/service/TrackServiceTest.java +++ b/src/test/java/com/cabin/plat/domain/track/service/TrackServiceTest.java @@ -13,6 +13,8 @@ import com.cabin.plat.domain.track.repository.LocationRepository; import com.cabin.plat.domain.track.repository.TrackReportRepository; import com.cabin.plat.domain.track.repository.TrackRepository; +import com.cabin.plat.global.exception.RestApiException; +import com.cabin.plat.global.exception.errorCode.TrackErrorCode; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -20,6 +22,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.transaction.annotation.Transactional; @@ -163,20 +166,6 @@ private List createTestTracks(List members, List locati .avatar(members.get(0).getAvatar()) .build(); - TrackResponse.TrackDetail expectedTrackDetail = TrackResponse.TrackDetail.builder() - .trackId(trackId) - .isrc("isrc1") - .latitude(36.017062) - .longitude(129.321993) - .buildingName("Dormitory 16 (DICE)") - .address("경상북도 포항시 남구 지곡동 287") - .imageUrl("https://testimage1.com") - .content("기숙사에서 한곡") - .likeCount(0) - .isLiked(false) - .member(memberInfo) - .build(); - // when TrackResponse.TrackDetail trackDetail = trackService.getTrackById(members.get(0), trackId); @@ -195,7 +184,7 @@ private List createTestTracks(List members, List locati } @Nested - class TrackLikeTests { + class 트랙_좋아요_테스트 { private Long trackId; private Member member0; @@ -315,6 +304,36 @@ void setUp() { assertThat(thirdPageTracks).hasSize(0); } + @Nested + class 트랙_삭제_테스트 { + @Test + void 트랙_삭제_성공() { + // given + Member uploader = members.get(0); + Long trackId = tracks.get(0).getId(); + + // when + TrackResponse.TrackId deletedTrackId = trackService.deleteTrack(uploader, trackId); + + // then + assertThat(deletedTrackId.getTrackId()).isEqualTo(trackId); + Optional track = trackRepository.findById(trackId); + assertThat(track.isPresent()).isTrue(); + assertThat(track.get().getDeletedAt()).isNotNull(); + } + + @Test + void 트랙_삭제_실패_권한없음() { + // given + Member nonUploader = members.get(2); // 다른 멤버 + Long trackId = tracks.get(0).getId(); // 삭제하려는 트랙의 ID + + // when, then + assertThatThrownBy(() -> trackService.deleteTrack(nonUploader, trackId)) + .isInstanceOf(RestApiException.class); + } + } + @Test void 트랙_신고() { // given