diff --git a/src/main/java/org/example/siljeun/domain/concert/service/ConcertCacheService.java b/src/main/java/org/example/siljeun/domain/concert/service/ConcertCacheService.java index b70598d..5c867a3 100644 --- a/src/main/java/org/example/siljeun/domain/concert/service/ConcertCacheService.java +++ b/src/main/java/org/example/siljeun/domain/concert/service/ConcertCacheService.java @@ -1,5 +1,6 @@ package org.example.siljeun.domain.concert.service; +import java.time.Duration; import java.util.List; import java.util.Set; import lombok.RequiredArgsConstructor; @@ -18,6 +19,12 @@ public class ConcertCacheService { public void increaseViewCount(Long concertId) { redisTemplate.opsForZSet().incrementScore(RANK_KEY, concertId, 1); + + redisTemplate.opsForZSet().incrementScore("ranking:daily", concertId, 1); + ensureTtl("ranking:daily", Duration.ofDays(1)); + + redisTemplate.opsForZSet().incrementScore("ranking:weekly", concertId, 1); + ensureTtl("ranking:weekly", Duration.ofDays(7)); } public List getTopConcertIds(int limit) { @@ -35,4 +42,11 @@ public List getTopConcertIds(String key, int limit) { return ids.stream().map(id -> Long.valueOf(id.toString())).toList(); } + private void ensureTtl(String key, Duration ttl) { + Long expire = redisTemplate.getExpire(key); + if (expire == null || expire < 0) { + redisTemplate.expire(key, ttl); + } + } + } diff --git a/src/main/java/org/example/siljeun/domain/concert/service/ConcertServiceImpl.java b/src/main/java/org/example/siljeun/domain/concert/service/ConcertServiceImpl.java index 79e0216..784948d 100644 --- a/src/main/java/org/example/siljeun/domain/concert/service/ConcertServiceImpl.java +++ b/src/main/java/org/example/siljeun/domain/concert/service/ConcertServiceImpl.java @@ -36,8 +36,8 @@ public class ConcertServiceImpl implements ConcertService { @Override @Transactional public Long createConcert(ConcertCreateRequest request, Long userId) { - Venue venue = venueRepository.findById(request.venuId()) - .orElseThrow(() -> new EntityNotFoundException("존재하지 않는 공연장입니다.")); + Venue venue = venueRepository.findByIdAndDeletedAtIsNull(request.venuId()) + .orElseThrow(() -> new EntityNotFoundException("존재하지 않거나 삭제된 공연장입니다.")); Concert concert = Concert.builder() .title(request.title()) @@ -56,8 +56,8 @@ public void updateConcert(Long concertId, ConcertUpdateRequest request) { Concert concert = concertRepository.findById(concertId) .orElseThrow(() -> new EntityNotFoundException("해당 공연이 존재하지 않습니다.")); - Venue venue = venueRepository.findById(request.venueId()) - .orElseThrow(() -> new EntityNotFoundException("존재하지 않는 공연장입니다.")); + Venue venue = venueRepository.findByIdAndDeletedAtIsNull(request.venueId()) + .orElseThrow(() -> new EntityNotFoundException("존재하지 않거나 삭제된 공연장입니다.")); concert.update( request.title(), @@ -94,6 +94,11 @@ public ConcertDetailResponse getConcertDetail(Long concertId) { Concert concert = concertRepository.findById(concertId) .orElseThrow(() -> new EntityNotFoundException("해당 공연이 존재하지 않습니다.")); + Venue venue = concert.getVenue(); + if (venue.isDeleted()) { + throw new IllegalStateException("해당 공연장은 삭제되어 공연 상세 정보를 조회할 수 없습니다."); + } + VenueSimpleResponse venueResponse = new VenueSimpleResponse( concert.getVenue().getId(), concert.getVenue().getName(), diff --git a/src/main/java/org/example/siljeun/domain/venue/entity/Venue.java b/src/main/java/org/example/siljeun/domain/venue/entity/Venue.java index 346d5c2..cf39d82 100644 --- a/src/main/java/org/example/siljeun/domain/venue/entity/Venue.java +++ b/src/main/java/org/example/siljeun/domain/venue/entity/Venue.java @@ -6,6 +6,7 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; +import java.time.LocalDate; import lombok.Getter; import lombok.NoArgsConstructor; import org.example.siljeun.global.entity.BaseEntity; @@ -29,6 +30,8 @@ public class Venue extends BaseEntity { @Column(nullable = false) private Integer seatCapacity; + private LocalDate deletedAt; + public Venue(String name, String location, int seatCapacity) { this.name = name; this.location = location; @@ -40,4 +43,12 @@ public void update(String name, String location, int seatCapacity) { this.location = location; this.seatCapacity = seatCapacity; } + + public void softDelete() { + this.deletedAt = LocalDate.now(); + } + + public boolean isDeleted() { + return this.deletedAt != null; + } } \ No newline at end of file diff --git a/src/main/java/org/example/siljeun/domain/venue/repository/VenueRepository.java b/src/main/java/org/example/siljeun/domain/venue/repository/VenueRepository.java index bbd3c3b..281d0f5 100644 --- a/src/main/java/org/example/siljeun/domain/venue/repository/VenueRepository.java +++ b/src/main/java/org/example/siljeun/domain/venue/repository/VenueRepository.java @@ -1,8 +1,13 @@ package org.example.siljeun.domain.venue.repository; +import java.util.List; +import java.util.Optional; import org.example.siljeun.domain.venue.entity.Venue; import org.springframework.data.jpa.repository.JpaRepository; public interface VenueRepository extends JpaRepository { - + + List findAllByDeletedAtIsNull(); + + Optional findByIdAndDeletedAtIsNull(Long id); } diff --git a/src/main/java/org/example/siljeun/domain/venue/service/VenueServiceImpl.java b/src/main/java/org/example/siljeun/domain/venue/service/VenueServiceImpl.java index 1f54c9a..2727731 100644 --- a/src/main/java/org/example/siljeun/domain/venue/service/VenueServiceImpl.java +++ b/src/main/java/org/example/siljeun/domain/venue/service/VenueServiceImpl.java @@ -38,7 +38,14 @@ public void updateVenue(Long venueId, VenueUpdateRequest request) { @Override public void deleteVenue(Long venueId) { - venueRepository.deleteById(venueId); + Venue venue = venueRepository.findById(venueId) + .orElseThrow(() -> new EntityNotFoundException("해당 공연장을 찾을 수 없습니다.")); + + if (venue.isDeleted()) { + throw new IllegalStateException("이미 삭제된 공연장입니다."); + } + + venue.softDelete(); } }