From 4f6db529135d7006f6256e202e987e3a7dcce79c Mon Sep 17 00:00:00 2001 From: Seokjin Jeon Date: Fri, 19 Apr 2024 03:18:23 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[BE]=20refactor:=20MockData=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EB=A6=AC=ED=8C=A9=ED=84=B0?= =?UTF-8?q?=EB=A7=81=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=86=8D?= =?UTF-8?q?=EB=8F=84=20=EA=B0=9C=EC=84=A0=20(#839)=20(#860)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 중복으로 실행되는 Mock Data 설정 수정 - MockScheduler initialDelay 추가 - CommandLineAppStartupRunner MockScheduler 의존 제거 * refactor: Mock 아티스트, 학교 생성 로직 분리 * test: 테스트 코드 개선 - 일부 테스트 로직 간결하게 변경 - 트랜잭션 제거 * feat: 도메인 엔티티를 반환하는 MockGenerator 구현 * refactor: Mock 생성 로직 MockGenerator를 사용하도록 리팩터링 * refactor: 패키지 위치 정리, MockDataServiceIntegrationTest 검증 로직 정리 * refactor: 사용하지 않는 클래스 제거 * refactor: 어플리케이션 실행마다 축제 생성 방지 * refactor: 클래스, 메서드 명 명확하게 변경 * fix: 스케줄러 TimeUnit 수정 * feat: MockDataStartupInitializer 트랜잭션 적용하여 원자성 보장 * chore: 메서드명 수정 * chore: 학교 이름 뒤 추가하는 인덱스 제거 * refactor: 축제 생성 시 이름 "테코대학교 20770630 축제" 와 같은 포맷으로 변경 * test: given-when-then 잘못된 위치 수정 * chore: MockStageArtistsGenerator Javadoc 추가 * feat: MockFestivalDurationGenerator 추가 * refactor: 비즈니스 로직에 사용되는 변수 도메인으로 이동 및 MockFestivalDurationGenerator 사용하도록 변경 * feat: StageArtist notNull 검증 추가 - stageId, artistId --- .../festival/domain/FestivalDuration.java | 47 +++ .../mock/CommandLineAppStartupRunner.java | 22 -- ...ler.java => MockDataInitialScheduler.java} | 13 +- .../com/festago/mock/MockDataService.java | 216 -------------- .../mock/MockDataStartupInitializer.java | 29 ++ .../mock/MockFestivalDateGenerator.java | 10 - .../mock/RandomMockFestivalDateGenerator.java | 31 -- .../mock/application/MockDataService.java | 65 ++++ .../festago/mock/{ => domain}/MockArtist.java | 2 +- .../mock/domain/MockArtistsGenerator.java | 20 ++ .../domain/MockFestivalDurationGenerator.java | 9 + .../mock/domain/MockFestivalsGenerator.java | 37 +++ .../mock/domain/MockSchoolsGenerator.java | 39 +++ .../domain/MockStageArtistsGenerator.java | 59 ++++ .../mock/domain/MockStagesGenerator.java | 28 ++ .../RandomMockFestivalDurationGenerator.java | 25 ++ .../ForMockFestivalInfoRepository.java | 8 - .../ForMockStageQueryInfoRepository.java | 8 - .../com/festago/stage/domain/StageArtist.java | 7 + .../mock/application/MockDataServiceTest.java | 280 ------------------ .../MockDataServiceIntegrationTest.java | 51 ++++ .../festago/mock/config/MockDataConfig.java | 68 ----- .../mock/domain/MockArtistsGeneratorTest.java | 31 ++ .../domain/MockFestivalsGeneratorTest.java | 56 ++++ .../mock/domain/MockSchoolsGeneratorTest.java | 32 ++ .../domain/MockStageArtistsGeneratorTest.java | 111 +++++++ .../mock/domain/MockStagesGeneratorTest.java | 41 +++ 27 files changed, 695 insertions(+), 650 deletions(-) create mode 100644 backend/src/main/java/com/festago/festival/domain/FestivalDuration.java delete mode 100644 backend/src/main/java/com/festago/mock/CommandLineAppStartupRunner.java rename backend/src/main/java/com/festago/mock/{MockScheduler.java => MockDataInitialScheduler.java} (51%) delete mode 100644 backend/src/main/java/com/festago/mock/MockDataService.java create mode 100644 backend/src/main/java/com/festago/mock/MockDataStartupInitializer.java delete mode 100644 backend/src/main/java/com/festago/mock/MockFestivalDateGenerator.java delete mode 100644 backend/src/main/java/com/festago/mock/RandomMockFestivalDateGenerator.java create mode 100644 backend/src/main/java/com/festago/mock/application/MockDataService.java rename backend/src/main/java/com/festago/mock/{ => domain}/MockArtist.java (99%) create mode 100644 backend/src/main/java/com/festago/mock/domain/MockArtistsGenerator.java create mode 100644 backend/src/main/java/com/festago/mock/domain/MockFestivalDurationGenerator.java create mode 100644 backend/src/main/java/com/festago/mock/domain/MockFestivalsGenerator.java create mode 100644 backend/src/main/java/com/festago/mock/domain/MockSchoolsGenerator.java create mode 100644 backend/src/main/java/com/festago/mock/domain/MockStageArtistsGenerator.java create mode 100644 backend/src/main/java/com/festago/mock/domain/MockStagesGenerator.java create mode 100644 backend/src/main/java/com/festago/mock/domain/RandomMockFestivalDurationGenerator.java delete mode 100644 backend/src/main/java/com/festago/mock/repository/ForMockFestivalInfoRepository.java delete mode 100644 backend/src/main/java/com/festago/mock/repository/ForMockStageQueryInfoRepository.java delete mode 100644 backend/src/test/java/com/festago/mock/application/MockDataServiceTest.java create mode 100644 backend/src/test/java/com/festago/mock/application/integration/MockDataServiceIntegrationTest.java delete mode 100644 backend/src/test/java/com/festago/mock/config/MockDataConfig.java create mode 100644 backend/src/test/java/com/festago/mock/domain/MockArtistsGeneratorTest.java create mode 100644 backend/src/test/java/com/festago/mock/domain/MockFestivalsGeneratorTest.java create mode 100644 backend/src/test/java/com/festago/mock/domain/MockSchoolsGeneratorTest.java create mode 100644 backend/src/test/java/com/festago/mock/domain/MockStageArtistsGeneratorTest.java create mode 100644 backend/src/test/java/com/festago/mock/domain/MockStagesGeneratorTest.java diff --git a/backend/src/main/java/com/festago/festival/domain/FestivalDuration.java b/backend/src/main/java/com/festago/festival/domain/FestivalDuration.java new file mode 100644 index 000000000..78cf543f6 --- /dev/null +++ b/backend/src/main/java/com/festago/festival/domain/FestivalDuration.java @@ -0,0 +1,47 @@ +package com.festago.festival.domain; + +import com.festago.common.exception.BadRequestException; +import com.festago.common.exception.ErrorCode; +import com.festago.common.util.Validator; +import jakarta.persistence.Embeddable; +import java.time.LocalDate; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@Embeddable +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class FestivalDuration { + + private LocalDate startDate; + private LocalDate endDate; + + public FestivalDuration(LocalDate startDate, LocalDate endDate) { + validate(startDate, endDate); + this.startDate = startDate; + this.endDate = endDate; + } + + private void validate(LocalDate startDate, LocalDate endDate) { + Validator.notNull(startDate, "startDate"); + Validator.notNull(endDate, "endDate"); + if (startDate.isAfter(endDate)) { + throw new BadRequestException(ErrorCode.INVALID_FESTIVAL_DURATION); + } + } + + public boolean isBeforeStartDate(LocalDate date) { + return startDate.isBefore(date); + } + + public boolean isNotInDuration(LocalDate date) { + return date.isBefore(startDate) || date.isAfter(endDate); + } + + public LocalDate getStartDate() { + return startDate; + } + + public LocalDate getEndDate() { + return endDate; + } +} diff --git a/backend/src/main/java/com/festago/mock/CommandLineAppStartupRunner.java b/backend/src/main/java/com/festago/mock/CommandLineAppStartupRunner.java deleted file mode 100644 index cde40d7a4..000000000 --- a/backend/src/main/java/com/festago/mock/CommandLineAppStartupRunner.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.festago.mock; - -import lombok.RequiredArgsConstructor; -import org.springframework.boot.CommandLineRunner; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Component; - -@Profile({"dev"}) -@Component -@RequiredArgsConstructor -public class CommandLineAppStartupRunner implements CommandLineRunner { - - private final MockDataService mockDataService; - private final MockScheduler mockScheduler; - - @Override - public void run(String... args) { - if (mockDataService.initialize()) { - mockScheduler.run(); - } - } -} diff --git a/backend/src/main/java/com/festago/mock/MockScheduler.java b/backend/src/main/java/com/festago/mock/MockDataInitialScheduler.java similarity index 51% rename from backend/src/main/java/com/festago/mock/MockScheduler.java rename to backend/src/main/java/com/festago/mock/MockDataInitialScheduler.java index 98d171068..814fce784 100644 --- a/backend/src/main/java/com/festago/mock/MockScheduler.java +++ b/backend/src/main/java/com/festago/mock/MockDataInitialScheduler.java @@ -1,21 +1,22 @@ package com.festago.mock; +import com.festago.mock.application.MockDataService; import java.util.concurrent.TimeUnit; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Profile; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -@Profile("dev") +@Profile({"dev"}) @Component @RequiredArgsConstructor -public class MockScheduler { +public class MockDataInitialScheduler { - private static final long SCHEDULER_CYCLE = 7; + private static final long DAYS_OF_WEEK = 7L; private final MockDataService mockDataService; - @Scheduled(fixedDelay = SCHEDULER_CYCLE, timeUnit = TimeUnit.DAYS) - public void run() { - mockDataService.makeMockFestivals((int) SCHEDULER_CYCLE); + @Scheduled(initialDelay = DAYS_OF_WEEK, fixedDelay = DAYS_OF_WEEK, timeUnit = TimeUnit.DAYS) + public void createMockFestivals() { + mockDataService.makeMockFestivals(); } } diff --git a/backend/src/main/java/com/festago/mock/MockDataService.java b/backend/src/main/java/com/festago/mock/MockDataService.java deleted file mode 100644 index 81081a7cc..000000000 --- a/backend/src/main/java/com/festago/mock/MockDataService.java +++ /dev/null @@ -1,216 +0,0 @@ -package com.festago.mock; - -import com.festago.artist.application.ArtistCommandService; -import com.festago.artist.domain.Artist; -import com.festago.artist.dto.command.ArtistCreateCommand; -import com.festago.common.exception.ErrorCode; -import com.festago.common.exception.NotFoundException; -import com.festago.festival.application.command.FestivalCommandFacadeService; -import com.festago.festival.domain.Festival; -import com.festago.festival.dto.command.FestivalCreateCommand; -import com.festago.mock.repository.ForMockArtistRepository; -import com.festago.mock.repository.ForMockFestivalRepository; -import com.festago.mock.repository.ForMockSchoolRepository; -import com.festago.school.application.SchoolCommandService; -import com.festago.school.domain.School; -import com.festago.school.domain.SchoolRegion; -import com.festago.school.dto.SchoolCreateCommand; -import com.festago.stage.application.command.StageCommandFacadeService; -import com.festago.stage.dto.command.StageCreateCommand; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.atomic.AtomicLong; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Profile({"dev"}) -@Service -@Transactional -@RequiredArgsConstructor -public class MockDataService { - - public static final int STAGE_ARTIST_COUNT = 3; - private static final AtomicLong festivalSequence = new AtomicLong(); - private static final int STAGE_START_HOUR = 19; - private static final int SCHOOL_PER_REGION = 3; - private static final int DATE_OFFSET = 1; - - private final MockFestivalDateGenerator mockFestivalDateGenerator; - private final ForMockSchoolRepository schoolRepository; - private final ForMockArtistRepository artistRepository; - private final ForMockFestivalRepository festivalRepository; - private final FestivalCommandFacadeService festivalCommandFacadeService; - private final StageCommandFacadeService stageCommandFacadeService; - private final ArtistCommandService artistCommandService; - private final SchoolCommandService schoolCommandService; - - public boolean initialize() { - if (alreadyInitialized()) { - return false; - } - initializeData(); - return true; - } - - private boolean alreadyInitialized() { - return !schoolRepository.findAll().isEmpty(); - } - - private void initializeData() { - initializeSchool(); - initializeArtist(); - } - - private void initializeSchool() { - for (SchoolRegion schoolRegion : SchoolRegion.values()) { - if (SchoolRegion.ANY.equals(schoolRegion)) { - continue; - } - makeRegionSchools(schoolRegion); - } - } - - /** - * 각 지역 별로 3개의 학교를 만듭니다. ex) 서울1대학교 서울2대학교 서울3대학교 - */ - private void makeRegionSchools(SchoolRegion schoolRegion) { - for (int i = 0; i < SCHOOL_PER_REGION; i++) { - String schoolName = String.format("%s%d대학교", schoolRegion.name(), i + 1); - String schoolEmail = String.format("%s%d.com", schoolRegion.name(), i + 1); - crateSchool(schoolRegion, schoolName, schoolEmail); - } - } - - private void crateSchool(SchoolRegion schoolRegion, String schoolName, String schoolEmail) { - schoolCommandService.createSchool(new SchoolCreateCommand( - schoolName, - schoolEmail, - schoolRegion, - null, - null - ) - ); - } - - private void initializeArtist() { - for (MockArtist artist : MockArtist.values()) { - artistCommandService.save(new ArtistCreateCommand( - artist.name(), - artist.getProfileImage(), - artist.getBackgroundImageUrl() - ) - ); - } - } - - public void makeMockFestivals(int availableFestivalDuration) { - List allSchool = schoolRepository.findAll(); - List allArtist = artistRepository.findAll(); - int artistSize = allArtist.size(); - if (STAGE_ARTIST_COUNT > artistSize) { - throw new IllegalArgumentException( - String.format("공연을 구성하기 위한 아티스트의 최소 수를 만족하지 못합니다 최소 수 : %d 현재 수 : %d", STAGE_ARTIST_COUNT, artistSize)); - } - for (School school : allSchool) { - makeFestival(availableFestivalDuration, school, allArtist); - } - } - - /** - * 현재 날짜 + 입력받은 축제 기간 안의 기간을 갖는 축제를 생성합니다. 이때 하나의 축제에 중복된 아티스트가 포함되지 않기 위해서 makeRandomArtists 라는 메서드를 통해 섞인 Artist - * 들의 큐가 생성됩니다. - */ - private void makeFestival(int availableFestivalDuration, School school, List artists) { - LocalDate now = LocalDate.now(); - LocalDate startDate = mockFestivalDateGenerator.makeRandomStartDate(availableFestivalDuration, now); - LocalDate endDate = mockFestivalDateGenerator.makeRandomEndDate(availableFestivalDuration, now, startDate); - - Long newFestivalId = festivalCommandFacadeService.createFestival(new FestivalCreateCommand( - school.getName() + "축제" + festivalSequence.incrementAndGet(), - startDate, - endDate, - "https://picsum.photos/536/354", - school.getId() - )); - - makeStages(newFestivalId, makeRandomArtists(artists)); - } - - private Queue makeRandomArtists(List artists) { - List randomArtists = new ArrayList<>(artists); - Collections.shuffle(randomArtists); - return new ArrayDeque<>(randomArtists); - } - - /** - * 축제 기간 동안 축제를 채웁니다. 에를 들어 Festival 이 23~25일 이라면 23, 24, 25 날짜의 stage 를 생성합니다. - */ - private void makeStages(Long festivalId, Queue artists) { - Festival festival = festivalRepository.findById(festivalId) - .orElseThrow(() -> new NotFoundException(ErrorCode.FESTIVAL_NOT_FOUND)); - LocalDate endDate = festival.getEndDate(); - LocalDate startDate = festival.getStartDate(); - startDate.datesUntil(endDate.plusDays(DATE_OFFSET)) - .forEach(localDate -> makeStage(festival, artists, localDate)); - } - - /** - * 실질적으로 무대를 만드는 부분으로 이때 하나의 stage 는 랜덤한 아티스트 3명을 갖도록 만듭니다. - * 축제 별로 생성되는 queue 에서 poll 을 통해 stageArtist 를 결정하기 때문에 같은 축제에서 아티스트는 중복되지 않습니다. - */ - private void makeStage(Festival festival, Queue artists, LocalDate localDate) { - LocalDateTime startTime = localDate.atTime(STAGE_START_HOUR, 0); - stageCommandFacadeService.createStage(new StageCreateCommand( - festival.getId(), - startTime, - startTime.minusDays(1L), - makeStageArtists(artists) - )); - } - - private List makeStageArtists(Queue artists) { - return makeStageArtistsByArtistCount(artists).stream() - .map(Artist::getId) - .toList(); - } - - /** - * Stage 는 생성 제약 조건에 의해서 무조건 다른 아티스트로 구성해야합니다. - * 만약 STAGE_ARTIST_COUNT * 2 값보다 큐에 artist 가 작게 들어있으면 poll 연산 이후 artist 는 STAGE_ARTIST_COUNT 보다 적게 들어있습니다. - * 예를 들어 STAGE_ARTIST_COUNT = 3 일떄 6개의 아티스트에 대해서 poll 를 한다면 3개가 남아 나머지 3개로 중복 없는Stage 를 구성할 수 있지만 - * 5개의 아티스트에 대해서 poll 한 후에 2개의 artist 로는 Stage 에 중복이 생길 수 밖에 없습니다. - * 따라서 STAGE_ARTIST_COUNT * 2 artists 가 크다면 poll, 아닐 경우 poll 이후 다시 insert 해주는 로직을 진행합니다. - */ - private List makeStageArtistsByArtistCount(Queue artists) { - if (artists.size() < STAGE_ARTIST_COUNT * 2) { - return makeDuplicateStageArtists(artists); - } - return makeUniqueStageArtists(artists); - } - - private List makeDuplicateStageArtists(Queue artists) { - List result = new ArrayList<>(); - for (int i = 0; i < STAGE_ARTIST_COUNT; i++) { - Artist artist = artists.poll(); - result.add(artist); - artists.add(artist); - } - return result; - } - - private List makeUniqueStageArtists(Queue artists) { - List result = new ArrayList<>(); - for (int i = 0; i < STAGE_ARTIST_COUNT; i++) { - Artist artist = artists.poll(); - result.add(artist); - } - return result; - } -} diff --git a/backend/src/main/java/com/festago/mock/MockDataStartupInitializer.java b/backend/src/main/java/com/festago/mock/MockDataStartupInitializer.java new file mode 100644 index 000000000..70302fe4e --- /dev/null +++ b/backend/src/main/java/com/festago/mock/MockDataStartupInitializer.java @@ -0,0 +1,29 @@ +package com.festago.mock; + +import com.festago.mock.application.MockDataService; +import com.festago.mock.repository.ForMockSchoolRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.annotation.Profile; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Profile({"dev"}) +@Component +@RequiredArgsConstructor +public class MockDataStartupInitializer { + + private final ForMockSchoolRepository forMockSchoolRepository; + private final MockDataService mockDataService; + + @Transactional + @EventListener(ApplicationReadyEvent.class) + public void initialize() { + if (forMockSchoolRepository.count() == 0) { + mockDataService.makeMockArtists(); + mockDataService.makeMockSchools(); + mockDataService.makeMockFestivals(); + } + } +} diff --git a/backend/src/main/java/com/festago/mock/MockFestivalDateGenerator.java b/backend/src/main/java/com/festago/mock/MockFestivalDateGenerator.java deleted file mode 100644 index 51b72e243..000000000 --- a/backend/src/main/java/com/festago/mock/MockFestivalDateGenerator.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.festago.mock; - -import java.time.LocalDate; - -public interface MockFestivalDateGenerator { - - LocalDate makeRandomStartDate(int festivalDuration, LocalDate now); - - LocalDate makeRandomEndDate(int festivalDuration, LocalDate now, LocalDate startDate); -} diff --git a/backend/src/main/java/com/festago/mock/RandomMockFestivalDateGenerator.java b/backend/src/main/java/com/festago/mock/RandomMockFestivalDateGenerator.java deleted file mode 100644 index 7ec66a5b5..000000000 --- a/backend/src/main/java/com/festago/mock/RandomMockFestivalDateGenerator.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.festago.mock; - -import java.time.LocalDate; -import java.time.temporal.ChronoUnit; -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Component; - -@Profile("dev") -@Component -public class RandomMockFestivalDateGenerator implements MockFestivalDateGenerator { - - private static final int COUNT_FIRST_DAY_AS_DURATION_ONE = 1; - private static final int RANDOM_OFFSET = 1; - private static final int MAX_END_DATE_FROM_START_DATE = 2; - private final Random random = ThreadLocalRandom.current(); - - @Override - public LocalDate makeRandomStartDate(int festivalDuration, LocalDate now) { - return now.plusDays(random.nextInt(festivalDuration)); - } - - @Override - public LocalDate makeRandomEndDate(int festivalDuration, LocalDate now, LocalDate startDate) { - long timeUntilFestivalStart = startDate.until(now, ChronoUnit.DAYS); - long maxAvailableEndDateFromStartDate = festivalDuration - (timeUntilFestivalStart + COUNT_FIRST_DAY_AS_DURATION_ONE); - int randomEndDate = random.nextInt((int) (maxAvailableEndDateFromStartDate + RANDOM_OFFSET)); - return startDate.plusDays(Math.min(randomEndDate, MAX_END_DATE_FROM_START_DATE)); - } -} diff --git a/backend/src/main/java/com/festago/mock/application/MockDataService.java b/backend/src/main/java/com/festago/mock/application/MockDataService.java new file mode 100644 index 000000000..988506f5a --- /dev/null +++ b/backend/src/main/java/com/festago/mock/application/MockDataService.java @@ -0,0 +1,65 @@ +package com.festago.mock.application; + +import com.festago.artist.domain.Artist; +import com.festago.festival.domain.Festival; +import com.festago.festival.dto.event.FestivalCreatedEvent; +import com.festago.mock.domain.MockArtistsGenerator; +import com.festago.mock.domain.MockFestivalsGenerator; +import com.festago.mock.domain.MockSchoolsGenerator; +import com.festago.mock.domain.MockStageArtistsGenerator; +import com.festago.mock.domain.MockStagesGenerator; +import com.festago.mock.repository.ForMockArtistRepository; +import com.festago.mock.repository.ForMockFestivalRepository; +import com.festago.mock.repository.ForMockSchoolRepository; +import com.festago.mock.repository.ForMockStageArtistRepository; +import com.festago.mock.repository.ForMockStageRepository; +import com.festago.school.domain.School; +import com.festago.stage.domain.Stage; +import com.festago.stage.dto.event.StageCreatedEvent; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class MockDataService { + + private final MockArtistsGenerator mockArtistsGenerator; + private final MockSchoolsGenerator mockSchoolsGenerator; + private final MockFestivalsGenerator mockFestivalsGenerator; + private final MockStagesGenerator mockStagesGenerator; + private final MockStageArtistsGenerator mockStageArtistsGenerator; + private final ForMockSchoolRepository schoolRepository; + private final ForMockArtistRepository artistRepository; + private final ForMockFestivalRepository festivalRepository; + private final ForMockStageRepository stageRepository; + private final ForMockStageArtistRepository stageArtistRepository; + private final ApplicationEventPublisher eventPublisher; + + public void makeMockArtists() { + artistRepository.saveAll(mockArtistsGenerator.generate()); + } + + public void makeMockSchools() { + schoolRepository.saveAll(mockSchoolsGenerator.generate()); + } + + public void makeMockFestivals() { + List artists = artistRepository.findAll(); + List schools = schoolRepository.findAll(); + List festivals = festivalRepository.saveAll( + mockFestivalsGenerator.generate(schools) + ); + for (Festival festival : festivals) { + List stages = stageRepository.saveAll(mockStagesGenerator.generate(festival)); + stageArtistRepository.saveAll(mockStageArtistsGenerator.generate(stages, artists)); + eventPublisher.publishEvent(new FestivalCreatedEvent(festival.getId())); + for (Stage stage : stages) { + eventPublisher.publishEvent(new StageCreatedEvent(stage)); + } + } + } +} diff --git a/backend/src/main/java/com/festago/mock/MockArtist.java b/backend/src/main/java/com/festago/mock/domain/MockArtist.java similarity index 99% rename from backend/src/main/java/com/festago/mock/MockArtist.java rename to backend/src/main/java/com/festago/mock/domain/MockArtist.java index ede1c5f65..c70e4ad70 100644 --- a/backend/src/main/java/com/festago/mock/MockArtist.java +++ b/backend/src/main/java/com/festago/mock/domain/MockArtist.java @@ -1,4 +1,4 @@ -package com.festago.mock; +package com.festago.mock.domain; public enum MockArtist { 윤하("https://i.namu.wiki/i/GXgnzRzEe4tq0YmevyZdmLNTPmVK2fzRyZtiCMA-0QSO8vbau9tah4rgP3qNokmT33-El0fx2PauysBruWpTk8B6MLu73gDgVnC3tvFeBnm3Lwo9oRreHM6slID3ilDTyFjpV2eKMO80Jf5u5E920g.webp", diff --git a/backend/src/main/java/com/festago/mock/domain/MockArtistsGenerator.java b/backend/src/main/java/com/festago/mock/domain/MockArtistsGenerator.java new file mode 100644 index 000000000..d66d92212 --- /dev/null +++ b/backend/src/main/java/com/festago/mock/domain/MockArtistsGenerator.java @@ -0,0 +1,20 @@ +package com.festago.mock.domain; + +import com.festago.artist.domain.Artist; +import java.util.Arrays; +import java.util.List; +import org.springframework.stereotype.Component; + +@Component +public class MockArtistsGenerator { + + public List generate() { + return Arrays.stream(MockArtist.values()) + .map(this::createArtist) + .toList(); + } + + private Artist createArtist(MockArtist mockArtist) { + return new Artist(mockArtist.name(), mockArtist.getProfileImage(), mockArtist.getBackgroundImageUrl()); + } +} diff --git a/backend/src/main/java/com/festago/mock/domain/MockFestivalDurationGenerator.java b/backend/src/main/java/com/festago/mock/domain/MockFestivalDurationGenerator.java new file mode 100644 index 000000000..7b5dcc7f7 --- /dev/null +++ b/backend/src/main/java/com/festago/mock/domain/MockFestivalDurationGenerator.java @@ -0,0 +1,9 @@ +package com.festago.mock.domain; + +import com.festago.festival.domain.FestivalDuration; +import java.time.LocalDate; + +public interface MockFestivalDurationGenerator { + + FestivalDuration generateFestivalDuration(LocalDate standardDate); +} diff --git a/backend/src/main/java/com/festago/mock/domain/MockFestivalsGenerator.java b/backend/src/main/java/com/festago/mock/domain/MockFestivalsGenerator.java new file mode 100644 index 000000000..db6374ce0 --- /dev/null +++ b/backend/src/main/java/com/festago/mock/domain/MockFestivalsGenerator.java @@ -0,0 +1,37 @@ +package com.festago.mock.domain; + +import com.festago.festival.domain.Festival; +import com.festago.festival.domain.FestivalDuration; +import com.festago.school.domain.School; +import java.time.Clock; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class MockFestivalsGenerator { + + private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd"); + private final Clock clock; + private final MockFestivalDurationGenerator festivalDurationGenerator; + + public List generate(List schools) { + LocalDate now = LocalDate.now(clock); + return schools.stream() + .map(school -> { + FestivalDuration festivalDuration = festivalDurationGenerator.generateFestivalDuration(now); + LocalDate startDate = festivalDuration.getStartDate(); + LocalDate endDate = festivalDuration.getEndDate(); + return new Festival( + school.getName() + " " + startDate.format(DATE_TIME_FORMATTER) + " 축제", + startDate, + endDate, + school + ); + }) + .toList(); + } +} diff --git a/backend/src/main/java/com/festago/mock/domain/MockSchoolsGenerator.java b/backend/src/main/java/com/festago/mock/domain/MockSchoolsGenerator.java new file mode 100644 index 000000000..9de356674 --- /dev/null +++ b/backend/src/main/java/com/festago/mock/domain/MockSchoolsGenerator.java @@ -0,0 +1,39 @@ +package com.festago.mock.domain; + +import com.festago.school.domain.School; +import com.festago.school.domain.SchoolRegion; +import java.util.Arrays; +import java.util.List; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import org.springframework.stereotype.Component; + +@Component +public class MockSchoolsGenerator { + + private static final int SCHOOL_PER_REGION = 3; + + public List generate() { + return Arrays.stream(SchoolRegion.values()) + .filter(it -> it != SchoolRegion.ANY) + .flatMap(this::crateSchools) + .toList(); + } + + private Stream crateSchools(SchoolRegion schoolRegion) { + return IntStream.rangeClosed(1, SCHOOL_PER_REGION) + .mapToObj(i -> { + String schoolName = String.format("%s%d대학교", schoolRegion.name(), i); + String schoolEmail = String.format("%s%d.com", schoolRegion.name(), i); + return crateSchool(schoolRegion, schoolName, schoolEmail); + }); + } + + private School crateSchool(SchoolRegion schoolRegion, String schoolName, String schoolEmail) { + return new School( + schoolEmail, + schoolName, + schoolRegion + ); + } +} diff --git a/backend/src/main/java/com/festago/mock/domain/MockStageArtistsGenerator.java b/backend/src/main/java/com/festago/mock/domain/MockStageArtistsGenerator.java new file mode 100644 index 000000000..74368170a --- /dev/null +++ b/backend/src/main/java/com/festago/mock/domain/MockStageArtistsGenerator.java @@ -0,0 +1,59 @@ +package com.festago.mock.domain; + +import com.festago.artist.domain.Artist; +import com.festago.common.exception.UnexpectedException; +import com.festago.stage.domain.Stage; +import com.festago.stage.domain.StageArtist; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Queue; +import org.springframework.stereotype.Component; + +@Component +public class MockStageArtistsGenerator { + + private static final int STAGE_PER_ARTIST = 3; + + /** + * 영속되지 않은 상태의 StageArtist 목록을 생성합니다.
StageArtist는 Stage와 Artist의 식별자가 필요하므로, 인자로 들어오는 Stage, Artist는 영속된 상태여야 + * 합니다.
공연에 STAGE_PER_ARTIST 만큼 아티스트를 참여시키는게 불가능할 경우, 각 공연 별 최소 1명은 참가하는 것을 보장합니다.
따라서, stages.size() > + * artists.size() 이면 예외가 발생합니다.
생성된 StageArtist 목록에는 중복된 Artist가 존재하지 않습니다.
+ * + * @param stages 영속 상태의 아티스트가 참여될 공연 목록 + * @param artists 영속 상태의 공연에 참여할 아티스트 목록 + * @return 중복된 Artist가 없는 영속되지 않은 StageArtist 엔티티 리스트 + * @throws UnexpectedException 공연의 개수가 아티스트의 개수를 초과하면 + */ + public List generate(List stages, List artists) { + if (stages.size() > artists.size()) { + throw new UnexpectedException("공연의 개수는 아티스트의 개수를 초과할 수 없습니다."); + } + Queue artistQueue = createShuffledArtistQueue(new ArrayList<>(artists)); + List stageArtists = new ArrayList<>(); + for (int i = 0; i < STAGE_PER_ARTIST; i++) { + appendStageArtist(stageArtists, stages, artistQueue); + } + return stageArtists; + } + + private Queue createShuffledArtistQueue(List artists) { + Collections.shuffle(artists); + return new ArrayDeque<>(artists); + } + + private void appendStageArtist( + List stageArtists, + List stages, + Queue artistQueue + ) { + for (Stage stage : stages) { + if (artistQueue.isEmpty()) { + return; + } + Artist artist = artistQueue.poll(); + stageArtists.add(new StageArtist(stage.getId(), artist.getId())); + } + } +} diff --git a/backend/src/main/java/com/festago/mock/domain/MockStagesGenerator.java b/backend/src/main/java/com/festago/mock/domain/MockStagesGenerator.java new file mode 100644 index 000000000..ac4f9bab6 --- /dev/null +++ b/backend/src/main/java/com/festago/mock/domain/MockStagesGenerator.java @@ -0,0 +1,28 @@ +package com.festago.mock.domain; + +import com.festago.festival.domain.Festival; +import com.festago.stage.domain.Stage; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import org.springframework.stereotype.Component; + +@Component +public class MockStagesGenerator { + + private static final long INCLUSIVE_VALUE = 1L; + private static final int STAGE_START_HOUR = 19; + + public List generate(Festival festival) { + LocalDate startDate = festival.getStartDate(); + LocalDate endDate = festival.getEndDate(); + return startDate.datesUntil(endDate.plusDays(INCLUSIVE_VALUE)) + .map(stageDate -> createStage(festival, stageDate)) + .toList(); + } + + private Stage createStage(Festival festival, LocalDate stageDate) { + LocalDateTime startTime = stageDate.atTime(STAGE_START_HOUR, 0); + return new Stage(startTime, startTime.minusWeeks(1), festival); + } +} diff --git a/backend/src/main/java/com/festago/mock/domain/RandomMockFestivalDurationGenerator.java b/backend/src/main/java/com/festago/mock/domain/RandomMockFestivalDurationGenerator.java new file mode 100644 index 000000000..4502767ca --- /dev/null +++ b/backend/src/main/java/com/festago/mock/domain/RandomMockFestivalDurationGenerator.java @@ -0,0 +1,25 @@ +package com.festago.mock.domain; + +import com.festago.festival.domain.FestivalDuration; +import java.time.LocalDate; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import org.springframework.stereotype.Component; + +@Component +public class RandomMockFestivalDurationGenerator implements MockFestivalDurationGenerator { + + private static final long DAYS_OF_WEEK = 7L; + private static final long INCLUSIVE_OFFSET = 1L; + private final Random random = ThreadLocalRandom.current(); + + @Override + public FestivalDuration generateFestivalDuration(LocalDate standardDate) { + long daysToAddStartDate = random.nextLong(DAYS_OF_WEEK + INCLUSIVE_OFFSET); // 0 ~ 7 + long daysToAddEndDate = random.nextLong( + DAYS_OF_WEEK + INCLUSIVE_OFFSET - daysToAddStartDate); // 0 ~ 7. if daysToAddStartDate == 7 ? 0 + LocalDate startDate = standardDate.plusDays(daysToAddStartDate); + LocalDate endDate = startDate.plusDays(daysToAddEndDate); + return new FestivalDuration(startDate, endDate); + } +} diff --git a/backend/src/main/java/com/festago/mock/repository/ForMockFestivalInfoRepository.java b/backend/src/main/java/com/festago/mock/repository/ForMockFestivalInfoRepository.java deleted file mode 100644 index 37f78f296..000000000 --- a/backend/src/main/java/com/festago/mock/repository/ForMockFestivalInfoRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.festago.mock.repository; - -import com.festago.festival.domain.FestivalQueryInfo; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface ForMockFestivalInfoRepository extends JpaRepository { - -} diff --git a/backend/src/main/java/com/festago/mock/repository/ForMockStageQueryInfoRepository.java b/backend/src/main/java/com/festago/mock/repository/ForMockStageQueryInfoRepository.java deleted file mode 100644 index 6a6480c63..000000000 --- a/backend/src/main/java/com/festago/mock/repository/ForMockStageQueryInfoRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.festago.mock.repository; - -import com.festago.stage.domain.StageQueryInfo; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface ForMockStageQueryInfoRepository extends JpaRepository { - -} diff --git a/backend/src/main/java/com/festago/stage/domain/StageArtist.java b/backend/src/main/java/com/festago/stage/domain/StageArtist.java index 1c8f65b83..f4dcf2cd4 100644 --- a/backend/src/main/java/com/festago/stage/domain/StageArtist.java +++ b/backend/src/main/java/com/festago/stage/domain/StageArtist.java @@ -1,5 +1,6 @@ package com.festago.stage.domain; +import com.festago.common.util.Validator; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -22,11 +23,17 @@ public StageArtist(Long stageId, Long artistId) { } public StageArtist(Long id, Long stageId, Long artistId) { + validate(stageId, artistId); this.id = id; this.stageId = stageId; this.artistId = artistId; } + private void validate(Long stageId, Long artistId) { + Validator.notNull(stageId, "stageId"); + Validator.notNull(artistId, "artistId"); + } + public Long getId() { return id; } diff --git a/backend/src/test/java/com/festago/mock/application/MockDataServiceTest.java b/backend/src/test/java/com/festago/mock/application/MockDataServiceTest.java deleted file mode 100644 index 7acf0249c..000000000 --- a/backend/src/test/java/com/festago/mock/application/MockDataServiceTest.java +++ /dev/null @@ -1,280 +0,0 @@ -package com.festago.mock.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.SoftAssertions.assertSoftly; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.doReturn; - -import com.festago.artist.domain.Artist; -import com.festago.festival.domain.Festival; -import com.festago.festival.domain.FestivalQueryInfo; -import com.festago.mock.MockArtist; -import com.festago.mock.MockDataService; -import com.festago.mock.MockFestivalDateGenerator; -import com.festago.mock.config.MockDataConfig; -import com.festago.mock.repository.ForMockArtistRepository; -import com.festago.mock.repository.ForMockFestivalInfoRepository; -import com.festago.mock.repository.ForMockFestivalRepository; -import com.festago.mock.repository.ForMockSchoolRepository; -import com.festago.mock.repository.ForMockStageArtistRepository; -import com.festago.mock.repository.ForMockStageQueryInfoRepository; -import com.festago.mock.repository.ForMockStageRepository; -import com.festago.school.domain.School; -import com.festago.school.domain.SchoolRegion; -import com.festago.stage.domain.Stage; -import com.festago.stage.domain.StageArtist; -import com.festago.stage.domain.StageQueryInfo; -import com.festago.support.ApplicationIntegrationTest; -import com.festago.support.fixture.SchoolFixture; -import java.time.LocalDate; -import java.time.temporal.ChronoUnit; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.stream.Collectors; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.context.annotation.Import; -import org.springframework.transaction.annotation.Transactional; - -@DisplayNameGeneration(ReplaceUnderscores.class) -@SuppressWarnings("NonAsciiCharacters") -@Import(MockDataConfig.class) -class MockDataServiceTest extends ApplicationIntegrationTest { - - private static final int INCLUDE_FIRST_DATE = 1; - @Autowired - ForMockArtistRepository artistRepository; - - @Autowired - ForMockSchoolRepository schoolRepository; - - @Autowired - ForMockFestivalRepository festivalRepository; - - @Autowired - ForMockStageRepository stageRepository; - - @Autowired - ForMockStageArtistRepository stageArtistRepository; - - @Autowired - ForMockStageQueryInfoRepository stageQueryInfoRepository; - - @Autowired - ForMockFestivalInfoRepository festivalInfoRepository; - - @SpyBean - MockFestivalDateGenerator mockFestivalDateGenerator; - - @Autowired - MockDataService mockDataService; - - @Nested - class 목_데이터_초기화는 { - - @Test - void 만약_하나의_학교라도_존재하면_초기화_된_상태로_판단한다() { - // given - schoolRepository.save(SchoolFixture.builder().build()); - - // when - mockDataService.initialize(); - List allSchool = schoolRepository.findAll(); - - // then - assertThat(allSchool).hasSize(1); - } - - @Test - void 학교가_없다면_ANY_를_제외한_지역_곱하기_3개만큼의_학교와_MOCK_ARTIST_만큼의_아티스트를_생성한다() { - // given - mockDataService.initialize(); - int expectGeneratedSchoolSize = (SchoolRegion.values().length - 1) * 3; - int expectArtistSize = MockArtist.values().length; - - // when - List allSchool = schoolRepository.findAll(); - List allArtist = artistRepository.findAll(); - - // then - assertSoftly(softly -> { - softly.assertThat(allSchool).hasSize(expectGeneratedSchoolSize); - softly.assertThat(allArtist).hasSize(expectArtistSize); - }); - } - } - - @Nested - class 목_축제_생성_요청은 { - - @Test - @Transactional - void 존재하는_학교수_만큼의_축제를_만들어_낸다() { - // given - mockDataService.initialize(); - List allSchool = schoolRepository.findAll(); - List beforeFestivals = festivalRepository.findAll(); - - // when - mockDataService.makeMockFestivals(7); - List afterFestivals = festivalRepository.findAll(); - List festivalSchools = afterFestivals.stream() - .map(festival -> festival.getSchool()) - .toList(); - - // then - assertSoftly(softly -> { - softly.assertThat(beforeFestivals).hasSize(0); - softly.assertThat(afterFestivals).hasSize(allSchool.size()); - softly.assertThat(festivalSchools).containsAll(allSchool); - }); - } - - @Test - void 쿼리_최적화_정보들을_생성한다() { - // given - mockDataService.initialize(); - mockDataService.makeMockFestivals(7); - - // when - List stageQueryInfos = stageQueryInfoRepository.findAll(); - List festivalQueryInfos = festivalInfoRepository.findAll(); - - // then - assertSoftly(softly -> { - assertThat(stageQueryInfos).isNotEmpty(); - assertThat(festivalQueryInfos).isNotEmpty(); - }); - } - - @Test - void 생성된_모든_축제는_기간은_전달_받은_기간_이내_이다() { - // given - mockDataService.initialize(); - mockDataService.makeMockFestivals(1); - - // when - List allFestival = festivalRepository.findAll(); - - // then - assertThat(allFestival).allMatch( - festival -> festival.getStartDate().until(festival.getStartDate(), ChronoUnit.DAYS) == 0); - } - - @Test - @Transactional - void 무대는_생성된_축제_기간동안_전부_존재한다() { - // given - LocalDate now = LocalDate.now(); - - mockDataService.initialize(); - mockDataService.makeMockFestivals(7); - List allFestival = festivalRepository.findAll(); - - // when - List allStage = stageRepository.findAll(); - Map> stageByFestival = allStage.stream() - .collect(Collectors.groupingBy(Stage::getFestival)); - - // then - assertThat(stageByFestival.entrySet()).allMatch(festivalListEntry -> { - Festival festival = festivalListEntry.getKey(); - long festivalDuration = - festival.getStartDate().until(festival.getEndDate(), ChronoUnit.DAYS) + INCLUDE_FIRST_DATE; - return festivalListEntry.getValue().size() == festivalDuration; - }); - } - - @Test - void 같은_축제_속_무대_아티스트_들은_겹치지_않는다() { - // given - mockDataService.initialize(); - mockDataService.makeMockFestivals(7); - - List stageArtists = stageArtistRepository.findAll(); - List allStage = stageRepository.findAll(); - - Map> stageArtistByStageId = stageArtists.stream() - .collect(Collectors.groupingBy(StageArtist::getStageId)); - Map> stageByFestival = allStage.stream() - .collect(Collectors.groupingBy(Stage::getFestival)); - - // when - Map> stageArtistsByFestival = new HashMap<>(); - - stageByFestival.forEach((festival, stages) -> { - List artistsForFestival = stages.stream() - .map(stage -> stageArtistByStageId.getOrDefault(stage.getId(), Collections.emptyList())) - .flatMap(List::stream) - .collect(Collectors.toList()); - - stageArtistsByFestival.put(festival, artistsForFestival); - }); - - // then - assertThat(stageArtistsByFestival.keySet()) - .allMatch(festival -> { - List stageArtistsValue = stageArtistsByFestival.get(festival); - long uniqueStageArtists = stageArtistsValue.stream() - .map(stageArtist -> stageArtist.getArtistId()) - .distinct() - .count(); - return stageArtistsValue.size() == uniqueStageArtists; - }); - } - - @Test - void 만약_아티스트가_중복없이_무대를_구성하기_부족하다면_중복을_허용한다() { - - // given - LocalDate now = LocalDate.now(); - int availableUniqueStageCount = MockArtist.values().length / MockDataService.STAGE_ARTIST_COUNT; - doReturn(now) - .when(mockFestivalDateGenerator) - .makeRandomStartDate(anyInt(), any(LocalDate.class)); - doReturn(now.plusDays(availableUniqueStageCount + 1)) - .when(mockFestivalDateGenerator) - .makeRandomEndDate(anyInt(), any(LocalDate.class), any(LocalDate.class)); - - mockDataService.initialize(); - mockDataService.makeMockFestivals(10); - - List stageArtists = stageArtistRepository.findAll(); - List allStage = stageRepository.findAll(); - - Map> stageArtistByStageId = stageArtists.stream() - .collect(Collectors.groupingBy(StageArtist::getStageId)); - Map> stageByFestival = allStage.stream() - .collect(Collectors.groupingBy(Stage::getFestival)); - - // when - Map> stageArtistsByFestival = new HashMap<>(); - - stageByFestival.forEach((festival, stages) -> { - List artistsForFestival = stages.stream() - .map(stage -> stageArtistByStageId.getOrDefault(stage.getId(), Collections.emptyList())) - .flatMap(List::stream) - .collect(Collectors.toList()); - - stageArtistsByFestival.put(festival, artistsForFestival); - }); - - List artistIds = stageArtistsByFestival.values().stream() - .flatMap(List::stream) - .map(stageArtist -> stageArtist.getArtistId()) - .toList(); - - // then - assertThat(artistIds.size()).isNotEqualTo(new HashSet<>(artistIds).size()); - } - } -} diff --git a/backend/src/test/java/com/festago/mock/application/integration/MockDataServiceIntegrationTest.java b/backend/src/test/java/com/festago/mock/application/integration/MockDataServiceIntegrationTest.java new file mode 100644 index 000000000..27a3776c9 --- /dev/null +++ b/backend/src/test/java/com/festago/mock/application/integration/MockDataServiceIntegrationTest.java @@ -0,0 +1,51 @@ +package com.festago.mock.application.integration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; + +import com.festago.mock.application.MockDataService; +import com.festago.support.ApplicationIntegrationTest; +import jakarta.persistence.EntityManager; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@DisplayNameGeneration(ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class MockDataServiceIntegrationTest extends ApplicationIntegrationTest { + + @Autowired + MockDataService mockDataService; + + @Autowired + EntityManager em; + + @Nested + class makeMockFestivals { + + @BeforeEach + void setUp() { + mockDataService.makeMockSchools(); + mockDataService.makeMockArtists(); + } + + @Test + void 쿼리_최적화_정보가_생성되어야_한다() { + // when + mockDataService.makeMockFestivals(); + + // then + Long stageQueryInfoCount = em.createQuery("select count(*) from StageQueryInfo sqi", Long.class) + .getSingleResult(); + Long festivalQueryInfoCount = em.createQuery("select count(*) from FestivalQueryInfo fqi", Long.class) + .getSingleResult(); + assertSoftly(softly -> { + assertThat(stageQueryInfoCount).isNotZero(); + assertThat(festivalQueryInfoCount).isNotZero(); + }); + } + } +} diff --git a/backend/src/test/java/com/festago/mock/config/MockDataConfig.java b/backend/src/test/java/com/festago/mock/config/MockDataConfig.java deleted file mode 100644 index ba4632540..000000000 --- a/backend/src/test/java/com/festago/mock/config/MockDataConfig.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.festago.mock.config; - -import com.festago.artist.application.ArtistCommandService; -import com.festago.artist.repository.ArtistRepository; -import com.festago.festival.application.command.FestivalCommandFacadeService; -import com.festago.festival.repository.FestivalRepository; -import com.festago.mock.CommandLineAppStartupRunner; -import com.festago.mock.MockScheduler; -import com.festago.mock.MockFestivalDateGenerator; -import com.festago.mock.MockDataService; -import com.festago.mock.RandomMockFestivalDateGenerator; -import com.festago.mock.repository.ForMockArtistRepository; -import com.festago.mock.repository.ForMockFestivalRepository; -import com.festago.mock.repository.ForMockSchoolRepository; -import com.festago.school.application.SchoolCommandService; -import com.festago.school.repository.SchoolRepository; -import com.festago.stage.application.command.StageCommandFacadeService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.context.annotation.Bean; - -@TestConfiguration -public class MockDataConfig { - - @Autowired - private ForMockSchoolRepository schoolRepository; - - @Autowired - private ForMockArtistRepository artistRepository; - - @Autowired - private ForMockFestivalRepository festivalRepository; - - @Autowired - private FestivalCommandFacadeService festivalCommandFacadeService; - - @Autowired - private StageCommandFacadeService stageCommandFacadeService; - - @Autowired - private ArtistCommandService artistCommandService; - - @Autowired - private SchoolCommandService schoolCommandService; - - - @Bean - public MockFestivalDateGenerator festivalDateGenerator() { - return new RandomMockFestivalDateGenerator(); - } - - @Bean - public MockDataService mockDataService() { - return new MockDataService(festivalDateGenerator(), schoolRepository, artistRepository, festivalRepository, - festivalCommandFacadeService, stageCommandFacadeService, artistCommandService, schoolCommandService); - } - - @Bean - public MockScheduler mockScheduler() { - return new MockScheduler(mockDataService()); - - } - - @Bean - public CommandLineAppStartupRunner commandLineAppStartupRunner() { - return new CommandLineAppStartupRunner(mockDataService(), mockScheduler()); - } -} diff --git a/backend/src/test/java/com/festago/mock/domain/MockArtistsGeneratorTest.java b/backend/src/test/java/com/festago/mock/domain/MockArtistsGeneratorTest.java new file mode 100644 index 000000000..65809f1d8 --- /dev/null +++ b/backend/src/test/java/com/festago/mock/domain/MockArtistsGeneratorTest.java @@ -0,0 +1,31 @@ +package com.festago.mock.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.festago.artist.domain.Artist; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class MockArtistsGeneratorTest { + + MockArtistsGenerator mockArtistsGenerator = new MockArtistsGenerator(); + + @Test + void MockArtist_목록으로_아티스트를_생성한다() { + // when + List actual = mockArtistsGenerator.generate(); + + // then + List expect = Arrays.stream(MockArtist.values()) + .map(Enum::name) + .toList(); + assertThat(actual) + .map(Artist::getName) + .containsExactlyInAnyOrderElementsOf(expect); + } +} diff --git a/backend/src/test/java/com/festago/mock/domain/MockFestivalsGeneratorTest.java b/backend/src/test/java/com/festago/mock/domain/MockFestivalsGeneratorTest.java new file mode 100644 index 000000000..cc986c3cc --- /dev/null +++ b/backend/src/test/java/com/festago/mock/domain/MockFestivalsGeneratorTest.java @@ -0,0 +1,56 @@ +package com.festago.mock.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.mock; +import static org.mockito.BDDMockito.spy; + +import com.festago.festival.domain.Festival; +import com.festago.festival.domain.FestivalDuration; +import com.festago.school.domain.School; +import com.festago.support.TimeInstantProvider; +import com.festago.support.fixture.SchoolFixture; +import java.time.Clock; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.IntStream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class MockFestivalsGeneratorTest { + + Clock clock; + MockFestivalDurationGenerator mockFestivalDurationGenerator; + MockFestivalsGenerator mockFestivalsGenerator; + + @BeforeEach + void setUp() { + clock = spy(Clock.systemDefaultZone()); + mockFestivalDurationGenerator = mock(MockFestivalDurationGenerator.class); + mockFestivalsGenerator = new MockFestivalsGenerator(clock, mockFestivalDurationGenerator); + } + + @Test + void 인자로_들어온_학교의_개수만큼_축제를_생성한다() { + // given + LocalDate now = LocalDate.parse("2077-06-30"); + given(clock.instant()) + .willReturn(TimeInstantProvider.from(now)); + given(mockFestivalDurationGenerator.generateFestivalDuration(any(LocalDate.class))) + .willReturn(new FestivalDuration(now, now)); + List schools = IntStream.rangeClosed(1, 10) + .mapToObj(i -> SchoolFixture.builder().build()) + .toList(); + + // when + List actual = mockFestivalsGenerator.generate(schools); + + // then + assertThat(actual).hasSize(schools.size()); + } +} diff --git a/backend/src/test/java/com/festago/mock/domain/MockSchoolsGeneratorTest.java b/backend/src/test/java/com/festago/mock/domain/MockSchoolsGeneratorTest.java new file mode 100644 index 000000000..f9586e191 --- /dev/null +++ b/backend/src/test/java/com/festago/mock/domain/MockSchoolsGeneratorTest.java @@ -0,0 +1,32 @@ +package com.festago.mock.domain; + +import static org.assertj.core.api.SoftAssertions.assertSoftly; + +import com.festago.school.domain.School; +import com.festago.school.domain.SchoolRegion; +import java.util.List; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class MockSchoolsGeneratorTest { + + MockSchoolsGenerator mockSchoolsGenerator = new MockSchoolsGenerator(); + + @Test + void SchoolRegion_ANY를_제외한_지역_당_3개의_학교를_생성한다() { + // when + List actual = mockSchoolsGenerator.generate(); + + // then + int expectSize = (SchoolRegion.values().length - 1) * 3; + assertSoftly(softly -> { + softly.assertThat(actual) + .map(School::getRegion) + .doesNotContain(SchoolRegion.ANY); + softly.assertThat(actual).hasSize(expectSize); + }); + } +} diff --git a/backend/src/test/java/com/festago/mock/domain/MockStageArtistsGeneratorTest.java b/backend/src/test/java/com/festago/mock/domain/MockStageArtistsGeneratorTest.java new file mode 100644 index 000000000..9f4059dad --- /dev/null +++ b/backend/src/test/java/com/festago/mock/domain/MockStageArtistsGeneratorTest.java @@ -0,0 +1,111 @@ +package com.festago.mock.domain; + +import static java.util.stream.Collectors.counting; +import static java.util.stream.Collectors.groupingBy; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.festago.artist.domain.Artist; +import com.festago.common.exception.UnexpectedException; +import com.festago.stage.domain.Stage; +import com.festago.stage.domain.StageArtist; +import com.festago.support.fixture.ArtistFixture; +import com.festago.support.fixture.StageFixture; +import java.util.List; +import java.util.Map; +import java.util.stream.LongStream; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class MockStageArtistsGeneratorTest { + + MockStageArtistsGenerator mockStageArtistsGenerator = new MockStageArtistsGenerator(); + + @Test + void 각_공연에_stagePerArtist_만큼_StageArtist를_생성한다() { + // given + int stageCount = 3; + int artistCount = 12; + List stages = createStages(stageCount); + List artists = createArtists(artistCount); + + // when + List actual = mockStageArtistsGenerator.generate(stages, artists); + + // then + Map stageIdToArtistCount = actual.stream() + .collect(groupingBy(StageArtist::getStageId, counting())); + assertThat(stageIdToArtistCount.values()) + .containsOnly(3L); + } + + @Test + void 생성된_StageArtist에는_중복된_Artist가_존재하지_않는다() { + // given + int stageCount = 3; + int artistCount = 9; + List stages = createStages(stageCount); + List artists = createArtists(artistCount); + + // when + long actual = mockStageArtistsGenerator.generate(stages, artists) + .stream() + .map(StageArtist::getArtistId) + .distinct() + .count(); + + // then + assertThat(actual).isEqualTo(artistCount); + } + + private List createStages(int stageCount) { + return LongStream.rangeClosed(1, stageCount) + .mapToObj(id -> StageFixture.builder().id(id).build()) + .toList(); + } + + private List createArtists(int artistCount) { + return LongStream.rangeClosed(1, artistCount) + .mapToObj(id -> ArtistFixture.builder().id(id).build()) + .toList(); + } + + @Test + void 공연의_개수가_아티스트의_개수를_초과하면_예외() { + // given + int stageCount = 11; + int artistCount = 10; + List stages = createStages(stageCount); + List artists = createArtists(artistCount); + + // when & then + assertThatThrownBy(() -> mockStageArtistsGenerator.generate(stages, artists)) + .isInstanceOf(UnexpectedException.class); + } + + @Nested + class 각_공연에_stagePerArtist_만큼_아티스트를_참여시키는_것이_불가능해도 { + + @Test + void 각_공연마다_아티스트가_참여하는_것을_보장한다() { + // given + int stageCount = 10; + int artistCount = 10; + List stages = createStages(stageCount); + List artists = createArtists(artistCount); + + // when + List actual = mockStageArtistsGenerator.generate(stages, artists); + + // then + Map stageIdToArtistCount = actual.stream() + .collect(groupingBy(StageArtist::getStageId, counting())); + assertThat(stageIdToArtistCount.values()) + .doesNotContain(0L); + } + } +} diff --git a/backend/src/test/java/com/festago/mock/domain/MockStagesGeneratorTest.java b/backend/src/test/java/com/festago/mock/domain/MockStagesGeneratorTest.java new file mode 100644 index 000000000..28e090390 --- /dev/null +++ b/backend/src/test/java/com/festago/mock/domain/MockStagesGeneratorTest.java @@ -0,0 +1,41 @@ +package com.festago.mock.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.festago.festival.domain.Festival; +import com.festago.stage.domain.Stage; +import com.festago.support.fixture.FestivalFixture; +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; +import java.util.List; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class MockStagesGeneratorTest { + + MockStagesGenerator mockStagesGenerator = new MockStagesGenerator(); + + @Test + void 축제의_모든_기간에_공연을_생성한다() { + // given + LocalDate now = LocalDate.parse("2077-06-30"); + Festival festival = FestivalFixture.builder() + .startDate(now) + .endDate(now.plusDays(2)) + .build(); + + // when + List actual = mockStagesGenerator.generate(festival); + + // then + LocalDate festivalStartDate = festival.getStartDate(); + LocalDate festivalEndDate = festival.getEndDate(); + long festivalPeriod = festivalStartDate.until(festivalEndDate, ChronoUnit.DAYS) + 1L; + assertThat(actual) + .size() + .isEqualTo(festivalPeriod); + } +} From df8dfb45b1677dff240861605f45c0fd87ee2b43 Mon Sep 17 00:00:00 2001 From: Seokjin Jeon Date: Fri, 19 Apr 2024 03:18:43 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[BE]=20build:=20Thymeleaf=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=20=EC=A0=9C=EA=B1=B0=20(#865)=20(#866)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build: Thymeleaf 의존 제거 --- backend/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index 8fc465a7f..286b55067 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -34,7 +34,6 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-validation") implementation("org.springframework.boot:spring-boot-starter-web") - implementation("org.springframework.boot:spring-boot-starter-thymeleaf") implementation("org.springframework.boot:spring-boot-starter-mail") implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:${swaggerVersion}") From 4899bac8a14606b6d9ec4acfeb7b4d9ba8f58dd8 Mon Sep 17 00:00:00 2001 From: Seokjin Jeon Date: Sat, 20 Apr 2024 21:40:59 +0900 Subject: [PATCH 3/5] =?UTF-8?q?[BE]=20fix:=20=ED=95=99=EA=B5=90=EC=9D=98?= =?UTF-8?q?=20=EC=B6=95=EC=A0=9C=20=EB=AA=A9=EB=A1=9D=EC=9D=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=A0=20=EB=95=8C=20last=20=EC=97=AC=EB=B6=80?= =?UTF-8?q?=EA=B0=80=20=EB=B0=98=EB=8C=80=EB=A1=9C=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=EB=A5=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#883)=20(#884)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: last 값이 반대로 나오는 버그 수정 --- .../school/repository/v1/SchoolV1QueryDslRepository.java | 6 +++--- .../integration/SchoolV1QueryServiceIntegrationTest.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/festago/school/repository/v1/SchoolV1QueryDslRepository.java b/backend/src/main/java/com/festago/school/repository/v1/SchoolV1QueryDslRepository.java index 25bc7ff78..e1e5f6c22 100644 --- a/backend/src/main/java/com/festago/school/repository/v1/SchoolV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/school/repository/v1/SchoolV1QueryDslRepository.java @@ -124,12 +124,12 @@ private Slice createResponse( Pageable pageable, List content ) { - boolean hasNext = true; + boolean hasNext = false; if (content.size() > pageable.getPageSize()) { content.remove(content.size() - 1); - hasNext = false; + hasNext = true; } - return new SliceImpl(content, pageable, hasNext); + return new SliceImpl<>(content, pageable, hasNext); } } diff --git a/backend/src/test/java/com/festago/school/application/integration/SchoolV1QueryServiceIntegrationTest.java b/backend/src/test/java/com/festago/school/application/integration/SchoolV1QueryServiceIntegrationTest.java index ca930b44d..5dc0da5d3 100644 --- a/backend/src/test/java/com/festago/school/application/integration/SchoolV1QueryServiceIntegrationTest.java +++ b/backend/src/test/java/com/festago/school/application/integration/SchoolV1QueryServiceIntegrationTest.java @@ -256,11 +256,11 @@ void setUp() { searchCondition); // then - assertThat(actual.hasNext()).isFalse(); + assertThat(actual.hasNext()).isTrue(); } @Test - void 다음_페이지가_존재하지않는다() { + void 다음_페이지가_존재하지_않는다() { // given saveFestival(today, today.plusDays(1)); var searchCondition = new SchoolFestivalV1SearchCondition(null, null, false, Pageable.ofSize(1)); @@ -270,7 +270,7 @@ void setUp() { school.getId(), today, searchCondition); // then - assertThat(actual.hasNext()).isTrue(); + assertThat(actual.hasNext()).isFalse(); } private Festival saveFestival(LocalDate startDate, LocalDate endDate) { From 0ba69ad029c961704e13c735d398e827fcc24df9 Mon Sep 17 00:00:00 2001 From: Seokjin Jeon Date: Sun, 21 Apr 2024 01:17:48 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[BE]=20feat:=20Festival=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20startDate,=20endDate=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=20FestivalDuration=20=EA=B0=92=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20thumbnail=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD=20(#880)=20(#881)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: Festival 엔티티 FestivalDuration 사용하도록 변경 * refactor: Festival 날짜 관련 메서드 FestivalDuration 위임 * refactor: createFestival 메서드 save 이전 validate 수행하도록 변경 - save 호출 시 auto increment 값 증가 문제 수정 및 효율 향상 * refactor: Festival thumbnail 필드 posterImageUrl으로 변경 --- ...minFestivalDetailV1QueryDslRepository.java | 6 +- .../AdminFestivalV1QueryDslRepository.java | 8 +- .../ArtistDetailV1QueryDslRepository.java | 22 ++-- .../FestivalBookmarkV1QueryDslRepository.java | 8 +- .../command/FestivalCreateService.java | 5 +- .../command/FestivalUpdateService.java | 5 +- .../com/festago/festival/domain/Festival.java | 96 +++++++--------- .../festival/domain/FestivalDuration.java | 2 +- .../dto/command/FestivalCreateCommand.java | 3 +- ...istFestivalSearchV1QueryDslRepository.java | 6 +- .../FestivalDetailV1QueryDslRepository.java | 6 +- .../FestivalV1QueryDslRepository.java | 32 +++--- .../PopularFestivalV1QueryDslRepository.java | 6 +- ...entSchoolFestivalV1QueryDslRepository.java | 4 +- ...oolFestivalSearchV1QueryDslRepository.java | 6 +- .../mock/domain/MockFestivalsGenerator.java | 7 +- .../v1/SchoolV1QueryDslRepository.java | 22 ++-- .../dto/MemberTicketFestivalResponse.java | 2 +- .../v1/AdminFestivalV1ControllerTest.java | 8 +- .../command/FestivalCreateServiceTest.java | 8 +- .../command/FestivalUpdateServiceTest.java | 12 +- .../festival/domain/FestivalDurationTest.java | 108 ++++++++++++++++++ .../festago/festival/domain/FestivalTest.java | 86 -------------- ...fDateStageFestivalUpdateValidatorTest.java | 14 ++- .../support/fixture/FestivalFixture.java | 4 +- 25 files changed, 250 insertions(+), 236 deletions(-) create mode 100644 backend/src/test/java/com/festago/festival/domain/FestivalDurationTest.java delete mode 100644 backend/src/test/java/com/festago/festival/domain/FestivalTest.java diff --git a/backend/src/main/java/com/festago/admin/repository/AdminFestivalDetailV1QueryDslRepository.java b/backend/src/main/java/com/festago/admin/repository/AdminFestivalDetailV1QueryDslRepository.java index 9b8c59fc5..2f722d763 100644 --- a/backend/src/main/java/com/festago/admin/repository/AdminFestivalDetailV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/admin/repository/AdminFestivalDetailV1QueryDslRepository.java @@ -23,9 +23,9 @@ public Optional findDetail(Long festivalId) { festival.name, school.id, school.name, - festival.startDate, - festival.endDate, - festival.thumbnail, + festival.festivalDuration.startDate, + festival.festivalDuration.endDate, + festival.posterImageUrl, festival.createdAt, festival.updatedAt ) diff --git a/backend/src/main/java/com/festago/admin/repository/AdminFestivalV1QueryDslRepository.java b/backend/src/main/java/com/festago/admin/repository/AdminFestivalV1QueryDslRepository.java index 18788ba57..fe7b6df76 100644 --- a/backend/src/main/java/com/festago/admin/repository/AdminFestivalV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/admin/repository/AdminFestivalV1QueryDslRepository.java @@ -34,8 +34,8 @@ public Page findAll(SearchCondition searchCondition) { festival.id, festival.name, school.name, - festival.startDate, - festival.endDate, + festival.festivalDuration.startDate, + festival.festivalDuration.endDate, stage.count() )) .from(festival) @@ -88,8 +88,8 @@ private OrderSpecifier getOrderSpecifier(Sort sort) { case "id" -> OrderSpecifierUtils.of(it.getDirection(), festival.id); case "name" -> OrderSpecifierUtils.of(it.getDirection(), festival.name); case "schoolName" -> OrderSpecifierUtils.of(it.getDirection(), school.name); - case "startDate" -> OrderSpecifierUtils.of(it.getDirection(), festival.startDate); - case "endDate" -> OrderSpecifierUtils.of(it.getDirection(), festival.endDate); + case "startDate" -> OrderSpecifierUtils.of(it.getDirection(), festival.festivalDuration.startDate); + case "endDate" -> OrderSpecifierUtils.of(it.getDirection(), festival.festivalDuration.endDate); default -> OrderSpecifierUtils.NULL; }) .orElse(OrderSpecifierUtils.NULL); diff --git a/backend/src/main/java/com/festago/artist/repository/ArtistDetailV1QueryDslRepository.java b/backend/src/main/java/com/festago/artist/repository/ArtistDetailV1QueryDslRepository.java index 1cabadb4d..859bc8996 100644 --- a/backend/src/main/java/com/festago/artist/repository/ArtistDetailV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/artist/repository/ArtistDetailV1QueryDslRepository.java @@ -96,9 +96,9 @@ private JPAQuery selectArtistDetailResponse(Long new QArtistFestivalDetailV1Response( festival.id, festival.name, - festival.startDate, - festival.endDate, - festival.thumbnail, + festival.festivalDuration.startDate, + festival.festivalDuration.endDate, + festival.posterImageUrl, festivalQueryInfo.artistInfo)) .from(stageArtist) .innerJoin(stage).on(stageArtist.artistId.eq(artistId).and(stage.id.eq(stageArtist.stageId))) @@ -124,26 +124,26 @@ private boolean hasCursor(LocalDate lastStartDate, Long lastFestivalId) { private BooleanExpression getCursorBasedWhere(boolean isPast, LocalDate lastStartDate, Long lastFestivalId) { if (isPast) { - return festival.startDate.lt(lastStartDate) - .or(festival.startDate.eq(lastStartDate) + return festival.festivalDuration.startDate.lt(lastStartDate) + .or(festival.festivalDuration.startDate.eq(lastStartDate) .and(festival.id.gt(lastFestivalId))); } - return festival.startDate.gt(lastStartDate) - .or(festival.startDate.eq(lastStartDate) + return festival.festivalDuration.startDate.gt(lastStartDate) + .or(festival.festivalDuration.startDate.eq(lastStartDate) .and(festival.id.gt(lastFestivalId))); } private BooleanExpression getDefaultWhere(boolean isPast, LocalDate currentTime) { if (isPast) { - return festival.endDate.lt(currentTime); + return festival.festivalDuration.endDate.lt(currentTime); } - return festival.endDate.goe(currentTime); + return festival.festivalDuration.endDate.goe(currentTime); } private OrderSpecifier[] getDynamicOrderBy(Boolean isPast) { if (isPast) { - return new OrderSpecifier[]{festival.endDate.desc()}; + return new OrderSpecifier[]{festival.festivalDuration.endDate.desc()}; } - return new OrderSpecifier[]{festival.startDate.asc(), festival.id.asc()}; + return new OrderSpecifier[]{festival.festivalDuration.startDate.asc(), festival.id.asc()}; } } diff --git a/backend/src/main/java/com/festago/bookmark/repository/v1/FestivalBookmarkV1QueryDslRepository.java b/backend/src/main/java/com/festago/bookmark/repository/v1/FestivalBookmarkV1QueryDslRepository.java index 4e1e31aee..d4a8d2f0d 100644 --- a/backend/src/main/java/com/festago/bookmark/repository/v1/FestivalBookmarkV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/bookmark/repository/v1/FestivalBookmarkV1QueryDslRepository.java @@ -41,9 +41,9 @@ public List findBookmarkedFestivals( new QFestivalV1Response( festival.id, festival.name, - festival.startDate, - festival.endDate, - festival.thumbnail, + festival.festivalDuration.startDate, + festival.festivalDuration.endDate, + festival.posterImageUrl, new QSchoolV1Response( school.id, school.name @@ -65,7 +65,7 @@ public List findBookmarkedFestivals( private OrderSpecifier dynamicOrder(FestivalBookmarkOrder festivalBookmarkOrder) { return switch (festivalBookmarkOrder) { case BOOKMARK -> bookmark.id.desc(); - case FESTIVAL -> festival.startDate.asc(); + case FESTIVAL -> festival.festivalDuration.startDate.asc(); }; } } diff --git a/backend/src/main/java/com/festago/festival/application/command/FestivalCreateService.java b/backend/src/main/java/com/festago/festival/application/command/FestivalCreateService.java index 776747c00..e57da91d0 100644 --- a/backend/src/main/java/com/festago/festival/application/command/FestivalCreateService.java +++ b/backend/src/main/java/com/festago/festival/application/command/FestivalCreateService.java @@ -27,14 +27,15 @@ public class FestivalCreateService { public Long createFestival(FestivalCreateCommand command) { School school = schoolRepository.getOrThrow(command.schoolId()); - Festival festival = festivalRepository.save(command.toEntity(school)); + Festival festival = command.toEntity(school); validate(festival); + festivalRepository.save(festival); eventPublisher.publishEvent(new FestivalCreatedEvent(festival.getId())); return festival.getId(); } private void validate(Festival festival) { - if (festival.isBeforeStartDate(LocalDate.now(clock))) { + if (festival.isStartDateBeforeTo(LocalDate.now(clock))) { throw new BadRequestException(ErrorCode.INVALID_FESTIVAL_START_DATE); } } diff --git a/backend/src/main/java/com/festago/festival/application/command/FestivalUpdateService.java b/backend/src/main/java/com/festago/festival/application/command/FestivalUpdateService.java index 89c47b130..5172236a7 100644 --- a/backend/src/main/java/com/festago/festival/application/command/FestivalUpdateService.java +++ b/backend/src/main/java/com/festago/festival/application/command/FestivalUpdateService.java @@ -1,6 +1,7 @@ package com.festago.festival.application.command; import com.festago.festival.domain.Festival; +import com.festago.festival.domain.FestivalDuration; import com.festago.festival.domain.validator.FestivalUpdateValidator; import com.festago.festival.dto.command.FestivalUpdateCommand; import com.festago.festival.repository.FestivalRepository; @@ -23,8 +24,8 @@ public class FestivalUpdateService { public void updateFestival(Long festivalId, FestivalUpdateCommand command) { Festival festival = festivalRepository.getOrThrow(festivalId); festival.changeName(command.name()); - festival.changeThumbnail(command.posterImageUrl()); - festival.changeDate(command.startDate(), command.endDate()); + festival.changePosterImageUrl(command.posterImageUrl()); + festival.changeFestivalDuration(new FestivalDuration(command.startDate(), command.endDate())); validators.forEach(validator -> validator.validate(festival)); } } diff --git a/backend/src/main/java/com/festago/festival/domain/Festival.java b/backend/src/main/java/com/festago/festival/domain/Festival.java index 502696e1c..a40ebd075 100644 --- a/backend/src/main/java/com/festago/festival/domain/Festival.java +++ b/backend/src/main/java/com/festago/festival/domain/Festival.java @@ -1,11 +1,9 @@ package com.festago.festival.domain; import com.festago.common.domain.BaseTimeEntity; -import com.festago.common.exception.BadRequestException; -import com.festago.common.exception.ErrorCode; import com.festago.common.util.Validator; import com.festago.school.domain.School; -import jakarta.persistence.Column; +import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; @@ -23,9 +21,9 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Festival extends BaseTimeEntity { - private static final String DEFAULT_THUMBNAIL = "https://picsum.photos/536/354"; + private static final String DEFAULT_POSTER_IMAGE_URL = "https://picsum.photos/536/354"; private static final int MAX_NAME_LENGTH = 50; - private static final int MAX_THUMBNAIL_LENGTH = 255; + private static final int MAX_POSTER_IMAGE_URL_LENGTH = 255; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -35,72 +33,63 @@ public class Festival extends BaseTimeEntity { @Size(max = MAX_NAME_LENGTH) private String name; - @NotNull - private LocalDate startDate; - - @NotNull - private LocalDate endDate; + @Embedded + private FestivalDuration festivalDuration; @NotNull - @Size(max = MAX_THUMBNAIL_LENGTH) - @Column(name = "poster_image_url") - private String thumbnail; + @Size(max = MAX_POSTER_IMAGE_URL_LENGTH) + private String posterImageUrl; @NotNull @ManyToOne(fetch = FetchType.LAZY) private School school; - public Festival(String name, LocalDate startDate, LocalDate endDate, School school) { - this(null, name, startDate, endDate, DEFAULT_THUMBNAIL, school); + public Festival(String name, FestivalDuration festivalDuration, School school) { + this(null, name, festivalDuration, DEFAULT_POSTER_IMAGE_URL, school); } - public Festival(String name, LocalDate startDate, LocalDate endDate, String thumbnail, School school) { - this(null, name, startDate, endDate, thumbnail, school); + public Festival(String name, FestivalDuration festivalDuration, String posterImageUrl, School school) { + this(null, name, festivalDuration, posterImageUrl, school); } - public Festival(Long id, String name, LocalDate startDate, LocalDate endDate, String thumbnail, School school) { - validate(name, startDate, endDate, thumbnail); + public Festival(Long id, String name, FestivalDuration festivalDuration, String posterImageUrl, School school) { + validateName(name); + validateFestivalDuration(festivalDuration); + validatePosterImageUrl(posterImageUrl); + validateSchool(school); this.id = id; this.name = name; - this.startDate = startDate; - this.endDate = endDate; - this.thumbnail = thumbnail; + this.festivalDuration = festivalDuration; + this.posterImageUrl = posterImageUrl; this.school = school; } - private void validate(String name, LocalDate startDate, LocalDate endDate, String thumbnail) { - validateName(name); - validateThumbnail(thumbnail); - validateDate(startDate, endDate); - } - private void validateName(String name) { String fieldName = "name"; Validator.notBlank(name, fieldName); Validator.maxLength(name, MAX_NAME_LENGTH, fieldName); } - private void validateThumbnail(String thumbnail) { - String fieldName = "thumbnail"; - Validator.notBlank(thumbnail, fieldName); - Validator.maxLength(thumbnail, MAX_THUMBNAIL_LENGTH, fieldName); + private void validatePosterImageUrl(String posterImageUrl) { + String fieldName = "posterImageUrl"; + Validator.notBlank(posterImageUrl, fieldName); + Validator.maxLength(posterImageUrl, MAX_POSTER_IMAGE_URL_LENGTH, fieldName); + } + + private void validateFestivalDuration(FestivalDuration festivalDuration) { + Validator.notNull(festivalDuration, "festivalDuration"); } - private void validateDate(LocalDate startDate, LocalDate endDate) { - Validator.notNull(startDate, "startDate"); - Validator.notNull(endDate, "endDate"); - if (startDate.isAfter(endDate)) { - throw new BadRequestException(ErrorCode.INVALID_FESTIVAL_DURATION); - } + private void validateSchool(School school) { + Validator.notNull(school, "school"); } - public boolean isBeforeStartDate(LocalDate currentDate) { - return startDate.isBefore(currentDate); + public boolean isStartDateBeforeTo(LocalDate date) { + return festivalDuration.isStartDateBeforeTo(date); } - public boolean isNotInDuration(LocalDateTime time) { - LocalDate date = time.toLocalDate(); - return date.isBefore(startDate) || date.isAfter(endDate); + public boolean isNotInDuration(LocalDateTime dateTime) { + return festivalDuration.isNotInDuration(dateTime.toLocalDate()); } public void changeName(String name) { @@ -108,15 +97,14 @@ public void changeName(String name) { this.name = name; } - public void changeThumbnail(String thumbnail) { - validateThumbnail(thumbnail); - this.thumbnail = thumbnail; + public void changePosterImageUrl(String posterImageUrl) { + validatePosterImageUrl(posterImageUrl); + this.posterImageUrl = posterImageUrl; } - public void changeDate(LocalDate startDate, LocalDate endDate) { - validateDate(startDate, endDate); - this.startDate = startDate; - this.endDate = endDate; + public void changeFestivalDuration(FestivalDuration festivalDuration) { + validateFestivalDuration(festivalDuration); + this.festivalDuration = festivalDuration; } public Long getId() { @@ -128,15 +116,15 @@ public String getName() { } public LocalDate getStartDate() { - return startDate; + return festivalDuration.getStartDate(); } public LocalDate getEndDate() { - return endDate; + return festivalDuration.getEndDate(); } - public String getThumbnail() { - return thumbnail; + public String getPosterImageUrl() { + return posterImageUrl; } public School getSchool() { diff --git a/backend/src/main/java/com/festago/festival/domain/FestivalDuration.java b/backend/src/main/java/com/festago/festival/domain/FestivalDuration.java index 78cf543f6..bf608d2ee 100644 --- a/backend/src/main/java/com/festago/festival/domain/FestivalDuration.java +++ b/backend/src/main/java/com/festago/festival/domain/FestivalDuration.java @@ -29,7 +29,7 @@ private void validate(LocalDate startDate, LocalDate endDate) { } } - public boolean isBeforeStartDate(LocalDate date) { + public boolean isStartDateBeforeTo(LocalDate date) { return startDate.isBefore(date); } diff --git a/backend/src/main/java/com/festago/festival/dto/command/FestivalCreateCommand.java b/backend/src/main/java/com/festago/festival/dto/command/FestivalCreateCommand.java index eb335cc8e..7db308a8a 100644 --- a/backend/src/main/java/com/festago/festival/dto/command/FestivalCreateCommand.java +++ b/backend/src/main/java/com/festago/festival/dto/command/FestivalCreateCommand.java @@ -1,6 +1,7 @@ package com.festago.festival.dto.command; import com.festago.festival.domain.Festival; +import com.festago.festival.domain.FestivalDuration; import com.festago.school.domain.School; import java.time.LocalDate; @@ -13,6 +14,6 @@ public record FestivalCreateCommand( ) { public Festival toEntity(School school) { - return new Festival(name, startDate, endDate, posterImageUrl, school); + return new Festival(name, new FestivalDuration(startDate, endDate), posterImageUrl, school); } } diff --git a/backend/src/main/java/com/festago/festival/repository/ArtistFestivalSearchV1QueryDslRepository.java b/backend/src/main/java/com/festago/festival/repository/ArtistFestivalSearchV1QueryDslRepository.java index 685acde9c..da4f277f6 100644 --- a/backend/src/main/java/com/festago/festival/repository/ArtistFestivalSearchV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/festival/repository/ArtistFestivalSearchV1QueryDslRepository.java @@ -43,9 +43,9 @@ private List searchByExpression(BooleanExpression expr new QFestivalSearchV1Response( festival.id, festival.name, - festival.startDate, - festival.endDate, - festival.thumbnail, + festival.festivalDuration.startDate, + festival.festivalDuration.endDate, + festival.posterImageUrl, festivalQueryInfo.artistInfo)) .from(artist) .innerJoin(stageArtist).on(expression.and(stageArtist.artistId.eq(artist.id))) diff --git a/backend/src/main/java/com/festago/festival/repository/FestivalDetailV1QueryDslRepository.java b/backend/src/main/java/com/festago/festival/repository/FestivalDetailV1QueryDslRepository.java index d94d37110..ddb1eb2ae 100644 --- a/backend/src/main/java/com/festago/festival/repository/FestivalDetailV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/festival/repository/FestivalDetailV1QueryDslRepository.java @@ -51,9 +51,9 @@ public Optional findFestivalDetail(Long festivalId) { school.id, school.name ), - festival.startDate, - festival.endDate, - festival.thumbnail, + festival.festivalDuration.startDate, + festival.festivalDuration.endDate, + festival.posterImageUrl, sortedSet(new QSocialMediaV1Response( socialMedia.mediaType, socialMedia.name, diff --git a/backend/src/main/java/com/festago/festival/repository/FestivalV1QueryDslRepository.java b/backend/src/main/java/com/festago/festival/repository/FestivalV1QueryDslRepository.java index 74262d4c1..05e5d8dae 100644 --- a/backend/src/main/java/com/festago/festival/repository/FestivalV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/festival/repository/FestivalV1QueryDslRepository.java @@ -45,9 +45,9 @@ private JPAQuery getSelectQuery() { return select(new QFestivalV1Response( festival.id, festival.name, - festival.startDate, - festival.endDate, - festival.thumbnail, + festival.festivalDuration.startDate, + festival.festivalDuration.endDate, + festival.posterImageUrl, new QSchoolV1Response( school.id, school.name @@ -94,16 +94,16 @@ private BooleanExpression getCursorBasedBooleanExpression( LocalDate lastStartDate ) { return switch (filter) { - case PLANNED -> festival.startDate.gt(lastStartDate) - .or(festival.startDate.eq(lastStartDate) + case PLANNED -> festival.festivalDuration.startDate.gt(lastStartDate) + .or(festival.festivalDuration.startDate.eq(lastStartDate) .and(festival.id.gt(lastFestivalId))); - case PROGRESS -> festival.startDate.lt(lastStartDate) - .or(festival.startDate.eq(lastStartDate) + case PROGRESS -> festival.festivalDuration.startDate.lt(lastStartDate) + .or(festival.festivalDuration.startDate.eq(lastStartDate) .and(festival.id.gt(lastFestivalId))) - .and(festival.endDate.goe(currentTime)); + .and(festival.festivalDuration.endDate.goe(currentTime)); - case END -> festival.endDate.lt(currentTime); + case END -> festival.festivalDuration.endDate.lt(currentTime); }; } @@ -112,12 +112,12 @@ private BooleanExpression getDefaultBooleanExpression( LocalDate currentTime ) { return switch (filter) { - case PLANNED -> festival.startDate.gt(currentTime); + case PLANNED -> festival.festivalDuration.startDate.gt(currentTime); - case PROGRESS -> festival.startDate.loe(currentTime) - .and(festival.endDate.goe(currentTime)); + case PROGRESS -> festival.festivalDuration.startDate.loe(currentTime) + .and(festival.festivalDuration.endDate.goe(currentTime)); - case END -> festival.endDate.lt(currentTime); + case END -> festival.festivalDuration.endDate.lt(currentTime); }; } @@ -130,9 +130,9 @@ private BooleanExpression applyRegion(BooleanExpression booleanExpression, Schoo private OrderSpecifier[] dynamicOrderBy(FestivalFilter filter) { return switch (filter) { - case PLANNED -> new OrderSpecifier[]{festival.startDate.asc(), festival.id.asc()}; - case PROGRESS -> new OrderSpecifier[]{festival.startDate.desc(), festival.id.asc()}; - case END -> new OrderSpecifier[]{festival.endDate.desc()}; + case PLANNED -> new OrderSpecifier[]{festival.festivalDuration.startDate.asc(), festival.id.asc()}; + case PROGRESS -> new OrderSpecifier[]{festival.festivalDuration.startDate.desc(), festival.id.asc()}; + case END -> new OrderSpecifier[]{festival.festivalDuration.endDate.desc()}; }; } diff --git a/backend/src/main/java/com/festago/festival/repository/PopularFestivalV1QueryDslRepository.java b/backend/src/main/java/com/festago/festival/repository/PopularFestivalV1QueryDslRepository.java index 21e9f2fd5..7470d13c4 100644 --- a/backend/src/main/java/com/festago/festival/repository/PopularFestivalV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/festival/repository/PopularFestivalV1QueryDslRepository.java @@ -28,9 +28,9 @@ public List findPopularFestivals() { return select(new QFestivalV1Response( festival.id, festival.name, - festival.startDate, - festival.endDate, - festival.thumbnail, + festival.festivalDuration.startDate, + festival.festivalDuration.endDate, + festival.posterImageUrl, new QSchoolV1Response( school.id, school.name diff --git a/backend/src/main/java/com/festago/festival/repository/RecentSchoolFestivalV1QueryDslRepository.java b/backend/src/main/java/com/festago/festival/repository/RecentSchoolFestivalV1QueryDslRepository.java index a061fe555..3f5c32694 100644 --- a/backend/src/main/java/com/festago/festival/repository/RecentSchoolFestivalV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/festival/repository/RecentSchoolFestivalV1QueryDslRepository.java @@ -24,10 +24,10 @@ public List findRecentSchoolFestivals( return select( new QSchoolSearchUpcomingFestivalV1Response( festival.school.id, - festival.startDate.min() + festival.festivalDuration.startDate.min() )) .from(festival) - .where(festival.school.id.in(schoolIds).and(festival.endDate.goe(now))) + .where(festival.school.id.in(schoolIds).and(festival.festivalDuration.endDate.goe(now))) .groupBy(festival.school.id) .fetch(); } diff --git a/backend/src/main/java/com/festago/festival/repository/SchoolFestivalSearchV1QueryDslRepository.java b/backend/src/main/java/com/festago/festival/repository/SchoolFestivalSearchV1QueryDslRepository.java index d09053f30..342474ef5 100644 --- a/backend/src/main/java/com/festago/festival/repository/SchoolFestivalSearchV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/festival/repository/SchoolFestivalSearchV1QueryDslRepository.java @@ -29,9 +29,9 @@ public List executeSearch(String keyword) { new QFestivalSearchV1Response( festival.id, festival.name, - festival.startDate, - festival.endDate, - festival.thumbnail, + festival.festivalDuration.startDate, + festival.festivalDuration.endDate, + festival.posterImageUrl, festivalQueryInfo.artistInfo)) .from(festival) .innerJoin(festivalQueryInfo).on(festival.id.eq(festivalQueryInfo.festivalId)) diff --git a/backend/src/main/java/com/festago/mock/domain/MockFestivalsGenerator.java b/backend/src/main/java/com/festago/mock/domain/MockFestivalsGenerator.java index db6374ce0..a5d01f4ef 100644 --- a/backend/src/main/java/com/festago/mock/domain/MockFestivalsGenerator.java +++ b/backend/src/main/java/com/festago/mock/domain/MockFestivalsGenerator.java @@ -23,12 +23,9 @@ public List generate(List schools) { return schools.stream() .map(school -> { FestivalDuration festivalDuration = festivalDurationGenerator.generateFestivalDuration(now); - LocalDate startDate = festivalDuration.getStartDate(); - LocalDate endDate = festivalDuration.getEndDate(); return new Festival( - school.getName() + " " + startDate.format(DATE_TIME_FORMATTER) + " 축제", - startDate, - endDate, + school.getName() + " " + festivalDuration.getStartDate().format(DATE_TIME_FORMATTER) + " 축제", + festivalDuration, school ); }) diff --git a/backend/src/main/java/com/festago/school/repository/v1/SchoolV1QueryDslRepository.java b/backend/src/main/java/com/festago/school/repository/v1/SchoolV1QueryDslRepository.java index e1e5f6c22..ee44414a4 100644 --- a/backend/src/main/java/com/festago/school/repository/v1/SchoolV1QueryDslRepository.java +++ b/backend/src/main/java/com/festago/school/repository/v1/SchoolV1QueryDslRepository.java @@ -66,9 +66,9 @@ public Slice findFestivalsBySchoolId(Long schoolId, Lo List result = select(new QSchoolFestivalV1Response(festival.id, festival.name, - festival.startDate, - festival.endDate, - festival.thumbnail, + festival.festivalDuration.startDate, + festival.festivalDuration.endDate, + festival.posterImageUrl, festivalQueryInfo.artistInfo ) ) @@ -87,21 +87,21 @@ public Slice findFestivalsBySchoolId(Long schoolId, Lo private BooleanExpression addPhaseOption(boolean isPast, LocalDate today) { if (isPast) { - return festival.endDate.lt(today); + return festival.festivalDuration.endDate.lt(today); } - return festival.endDate.goe(today); + return festival.festivalDuration.endDate.goe(today); } private BooleanExpression addPagingOption(Long lastFestivalId, LocalDate lastStartDate, boolean isPast) { if (isNotFirstPage(lastFestivalId, lastStartDate)) { if (isPast) { - return festival.startDate.lt(lastStartDate) - .or(festival.startDate.eq(lastStartDate) + return festival.festivalDuration.startDate.lt(lastStartDate) + .or(festival.festivalDuration.startDate.eq(lastStartDate) .and(festival.id.gt(lastFestivalId))); } - return festival.startDate.gt(lastStartDate) - .or(festival.startDate.eq(lastStartDate) + return festival.festivalDuration.startDate.gt(lastStartDate) + .or(festival.festivalDuration.startDate.eq(lastStartDate) .and(festival.id.gt(lastFestivalId))); } @@ -114,10 +114,10 @@ private boolean isNotFirstPage(Long lastFestivalId, LocalDate lastStartDate) { private OrderSpecifier addOrderOption(boolean isPast) { if (isPast) { - return festival.endDate.desc(); + return festival.festivalDuration.endDate.desc(); } - return festival.startDate.asc(); + return festival.festivalDuration.startDate.asc(); } private Slice createResponse( diff --git a/backend/src/main/java/com/festago/ticketing/dto/MemberTicketFestivalResponse.java b/backend/src/main/java/com/festago/ticketing/dto/MemberTicketFestivalResponse.java index 0b3779cf0..3d44b6796 100644 --- a/backend/src/main/java/com/festago/ticketing/dto/MemberTicketFestivalResponse.java +++ b/backend/src/main/java/com/festago/ticketing/dto/MemberTicketFestivalResponse.java @@ -11,6 +11,6 @@ public static MemberTicketFestivalResponse from(Festival festival) { return new MemberTicketFestivalResponse( festival.getId(), festival.getName(), - festival.getThumbnail()); + festival.getPosterImageUrl()); } } diff --git a/backend/src/test/java/com/festago/admin/presentation/v1/AdminFestivalV1ControllerTest.java b/backend/src/test/java/com/festago/admin/presentation/v1/AdminFestivalV1ControllerTest.java index 728ae7b24..f5bb98c64 100644 --- a/backend/src/test/java/com/festago/admin/presentation/v1/AdminFestivalV1ControllerTest.java +++ b/backend/src/test/java/com/festago/admin/presentation/v1/AdminFestivalV1ControllerTest.java @@ -77,8 +77,8 @@ class 올바른_주소로 { String name = "테코대학교 축제"; LocalDate startDate = LocalDate.parse("2024-01-31"); LocalDate endDate = LocalDate.parse("2024-02-01"); - String thumbnail = "https://image.com/image.png"; - FestivalV1CreateRequest request = new FestivalV1CreateRequest(name, startDate, endDate, thumbnail, 1L); + String posterImageUrl = "https://image.com/image.png"; + FestivalV1CreateRequest request = new FestivalV1CreateRequest(name, startDate, endDate, posterImageUrl, 1L); @Test @WithMockAuth(role = Role.ADMIN) @@ -126,8 +126,8 @@ class 올바른_주소로 { String name = "테코대학교 축제"; LocalDate startDate = LocalDate.parse("2024-01-31"); LocalDate endDate = LocalDate.parse("2024-02-01"); - String thumbnail = "https://image.com/image.png"; - FestivalV1UpdateRequest request = new FestivalV1UpdateRequest(name, startDate, endDate, thumbnail); + String posterImageUrl = "https://image.com/image.png"; + FestivalV1UpdateRequest request = new FestivalV1UpdateRequest(name, startDate, endDate, posterImageUrl); @Test @WithMockAuth(role = Role.ADMIN) diff --git a/backend/src/test/java/com/festago/festival/application/integration/command/FestivalCreateServiceTest.java b/backend/src/test/java/com/festago/festival/application/integration/command/FestivalCreateServiceTest.java index 1373fd990..3074c91ba 100644 --- a/backend/src/test/java/com/festago/festival/application/integration/command/FestivalCreateServiceTest.java +++ b/backend/src/test/java/com/festago/festival/application/integration/command/FestivalCreateServiceTest.java @@ -63,12 +63,12 @@ void setUp() { String festivalName = "테코대학교 축제"; LocalDate startDate = now.minusDays(1); LocalDate endDate = now.plusDays(3); - String thumbnail = "https://image.com/image.png"; + String posterImageUrl = "https://image.com/image.png"; var command = new FestivalCreateCommand( festivalName, startDate, endDate, - thumbnail, + posterImageUrl, schoolId ); @@ -84,12 +84,12 @@ void setUp() { String festivalName = "테코대학교 축제"; LocalDate startDate = now.plusDays(1); LocalDate endDate = now.plusDays(3); - String thumbnail = "https://image.com/image.png"; + String posterImageUrl = "https://image.com/image.png"; var command = new FestivalCreateCommand( festivalName, startDate, endDate, - thumbnail, + posterImageUrl, schoolId ); diff --git a/backend/src/test/java/com/festago/festival/application/integration/command/FestivalUpdateServiceTest.java b/backend/src/test/java/com/festago/festival/application/integration/command/FestivalUpdateServiceTest.java index 497c4d86a..5ad33ee4f 100644 --- a/backend/src/test/java/com/festago/festival/application/integration/command/FestivalUpdateServiceTest.java +++ b/backend/src/test/java/com/festago/festival/application/integration/command/FestivalUpdateServiceTest.java @@ -59,12 +59,12 @@ void setUp() { String newFestivalName = "변경된 축제"; LocalDate newStartDate = now.minusDays(1); LocalDate newEndDate = now.plusDays(1); - String newThumbnail = "https://image.com/new-image.png"; + String newPosterImageUrl = "https://image.com/new-image.png"; var command = new FestivalUpdateCommand( newFestivalName, newStartDate, newEndDate, - newThumbnail + newPosterImageUrl ); // when @@ -76,7 +76,7 @@ void setUp() { softly.assertThat(updatedFestival.getName()).isEqualTo(newFestivalName); softly.assertThat(updatedFestival.getStartDate()).isEqualTo(newStartDate); softly.assertThat(updatedFestival.getEndDate()).isEqualTo(newEndDate); - softly.assertThat(updatedFestival.getThumbnail()).isEqualTo(newThumbnail); + softly.assertThat(updatedFestival.getPosterImageUrl()).isEqualTo(newPosterImageUrl); }); } @@ -86,12 +86,12 @@ void setUp() { String newFestivalName = "변경된 축제"; LocalDate newStartDate = now.plusDays(1); LocalDate newEndDate = now.plusDays(1); - String newThumbnail = "https://image.com/new-image.png"; + String newPosterImageUrl = "https://image.com/new-image.png"; var command = new FestivalUpdateCommand( newFestivalName, newStartDate, newEndDate, - newThumbnail + newPosterImageUrl ); // when @@ -103,7 +103,7 @@ void setUp() { softly.assertThat(updatedFestival.getName()).isEqualTo(newFestivalName); softly.assertThat(updatedFestival.getStartDate()).isEqualTo(newStartDate); softly.assertThat(updatedFestival.getEndDate()).isEqualTo(newEndDate); - softly.assertThat(updatedFestival.getThumbnail()).isEqualTo(newThumbnail); + softly.assertThat(updatedFestival.getPosterImageUrl()).isEqualTo(newPosterImageUrl); }); } } diff --git a/backend/src/test/java/com/festago/festival/domain/FestivalDurationTest.java b/backend/src/test/java/com/festago/festival/domain/FestivalDurationTest.java new file mode 100644 index 000000000..2e9c9d62c --- /dev/null +++ b/backend/src/test/java/com/festago/festival/domain/FestivalDurationTest.java @@ -0,0 +1,108 @@ +package com.festago.festival.domain; + +import static com.festago.common.exception.ErrorCode.INVALID_FESTIVAL_DURATION; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.festago.common.exception.BadRequestException; +import com.festago.common.exception.ValidException; +import java.time.LocalDate; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class FestivalDurationTest { + + LocalDate _6월_15일 = LocalDate.parse("2077-06-15"); + LocalDate _6월_16일 = LocalDate.parse("2077-06-16"); + LocalDate _6월_17일 = LocalDate.parse("2077-06-17"); + + @ParameterizedTest + @CsvSource({"2077-06-15,", ",2077-06-15"}) + void 시작일_또는_종료일이_null이면_예외(LocalDate startDate, LocalDate endDate) { + // when & then + assertThatThrownBy(() -> new FestivalDuration(startDate, endDate)) + .isInstanceOf(ValidException.class); + } + + @Test + void 시작일이_종료일_이전이면_예외() { + // when & then + assertThatThrownBy(() -> new FestivalDuration(_6월_17일, _6월_16일)) + .isInstanceOf(BadRequestException.class) + .hasMessage(INVALID_FESTIVAL_DURATION.getMessage()); + } + + @Nested + class isBeforeStartDate { + + @Test + void 기간의_시작일이_주어진_날짜보다_이후이면_거짓() { + // given + FestivalDuration _6월_16일_6월_16일 = new FestivalDuration(_6월_16일, _6월_16일); + + // then + boolean actual = _6월_16일_6월_16일.isStartDateBeforeTo(_6월_15일); + + // then + assertThat(actual).isFalse(); + } + + @Test + void 시작일이_주어진_날짜에_포함되면_거짓() { + // given + FestivalDuration _6월_16일_6월_16일 = new FestivalDuration(_6월_16일, _6월_16일); + + // then + boolean actual = _6월_16일_6월_16일.isStartDateBeforeTo(_6월_16일); + + // then + assertThat(actual).isFalse(); + } + + @Test + void 시작일이_주어진_날짜_이전이면_참() { + // given + FestivalDuration _6월_16일_6월_16일 = new FestivalDuration(_6월_16일, _6월_16일); + + // then + boolean actual = _6월_16일_6월_16일.isStartDateBeforeTo(_6월_17일); + + // then + assertThat(actual).isTrue(); + } + } + + @Nested + class isNotInDuration { + + @Test + void 기간에_포함되면_거짓() { + // given + FestivalDuration _6월_15일_6월_17일 = new FestivalDuration(_6월_15일, _6월_17일); + + // when + boolean actual = _6월_15일_6월_17일.isNotInDuration(_6월_16일); + + // then + assertThat(actual).isFalse(); + } + + @Test + void 기간에_포함되지_않으면_참() { + // given + FestivalDuration _6월_16일_6월_17일 = new FestivalDuration(_6월_16일, _6월_17일); + + // when + boolean actual = _6월_16일_6월_17일.isNotInDuration(_6월_15일); + + // then + assertThat(actual).isTrue(); + } + } +} diff --git a/backend/src/test/java/com/festago/festival/domain/FestivalTest.java b/backend/src/test/java/com/festago/festival/domain/FestivalTest.java deleted file mode 100644 index 2fa57cbbb..000000000 --- a/backend/src/test/java/com/festago/festival/domain/FestivalTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.festago.festival.domain; - -import static com.festago.common.exception.ErrorCode.INVALID_FESTIVAL_DURATION; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import com.festago.common.exception.BadRequestException; -import com.festago.school.domain.School; -import com.festago.support.fixture.FestivalFixture; -import com.festago.support.fixture.SchoolFixture; -import java.time.LocalDate; -import java.time.LocalDateTime; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -@DisplayNameGeneration(ReplaceUnderscores.class) -@SuppressWarnings("NonAsciiCharacters") -class FestivalTest { - - @Test - void 시작일자가_종료일자_이전이면_예외() { - // given - LocalDate today = LocalDate.now(); - School school = SchoolFixture.builder().build(); - LocalDate tomorrow = today.plusDays(1); - - // when & then - assertThatThrownBy(() -> new Festival("테코대학교", tomorrow, today, school)) - .isInstanceOf(BadRequestException.class) - .hasMessage(INVALID_FESTIVAL_DURATION.getMessage()); - } - - @Nested - class 축제_기간_중이_아닌지_검사 { - - @Test - void 축제_시작_일자_이전이면_참() { - // given - LocalDateTime time = LocalDateTime.now(); - Festival festival = FestivalFixture.builder() - .startDate(time.plusDays(1).toLocalDate()) - .endDate(time.plusDays(4).toLocalDate()) - .build(); - - // when - boolean actual = festival.isNotInDuration(time); - - // then - assertThat(actual).isTrue(); - } - - @Test - void 축제_종료_일자_이후이면_참() { - // given - LocalDateTime time = LocalDateTime.now(); - Festival festival = FestivalFixture.builder() - .startDate(time.minusDays(4).toLocalDate()) - .endDate(time.minusDays(1).toLocalDate()) - .build(); - - // when - boolean actual = festival.isNotInDuration(time); - - // then - assertThat(actual).isTrue(); - } - - @Test - void 축제_기간중이면_거짓() { - // given - LocalDateTime time = LocalDateTime.now(); - Festival festival = FestivalFixture.builder() - .startDate(time.minusDays(1).toLocalDate()) - .endDate(time.toLocalDate()) - .build(); - - // when - boolean actual = festival.isNotInDuration(time); - - // then - assertThat(actual).isFalse(); - } - } -} diff --git a/backend/src/test/java/com/festago/stage/domain/validator/festival/OutOfDateStageFestivalUpdateValidatorTest.java b/backend/src/test/java/com/festago/stage/domain/validator/festival/OutOfDateStageFestivalUpdateValidatorTest.java index c6090a958..043a39730 100644 --- a/backend/src/test/java/com/festago/stage/domain/validator/festival/OutOfDateStageFestivalUpdateValidatorTest.java +++ b/backend/src/test/java/com/festago/stage/domain/validator/festival/OutOfDateStageFestivalUpdateValidatorTest.java @@ -6,6 +6,7 @@ import com.festago.common.exception.BadRequestException; import com.festago.common.exception.ErrorCode; import com.festago.festival.domain.Festival; +import com.festago.festival.domain.FestivalDuration; import com.festago.stage.repository.MemoryStageRepository; import com.festago.stage.repository.StageRepository; import com.festago.support.fixture.FestivalFixture; @@ -62,7 +63,8 @@ void setUp() { // given LocalDate startDate = festivalStartDate.minusDays(1); LocalDate endDate = festivalEndDate.plusDays(1); - 축제.changeDate(startDate, endDate); + + 축제.changeFestivalDuration(new FestivalDuration(startDate, endDate)); // when & then assertDoesNotThrow(() -> validator.validate(축제)); @@ -73,7 +75,7 @@ void setUp() { // given LocalDate startDate = festivalStartDate.plusDays(1); LocalDate endDate = festivalEndDate; - 축제.changeDate(startDate, endDate); + 축제.changeFestivalDuration(new FestivalDuration(startDate, endDate)); // when & then assertThatThrownBy(() -> validator.validate(축제)) @@ -86,7 +88,7 @@ void setUp() { // given LocalDate startDate = festivalStartDate; LocalDate endDate = festivalEndDate.minusDays(1); - 축제.changeDate(startDate, endDate); + 축제.changeFestivalDuration(new FestivalDuration(startDate, endDate)); // when & then assertThatThrownBy(() -> validator.validate(축제)) @@ -103,7 +105,7 @@ class 축제에_등록된_공연이_없을때 { // given LocalDate startDate = festivalStartDate.minusDays(1); LocalDate endDate = festivalEndDate.plusDays(1); - 축제.changeDate(startDate, endDate); + 축제.changeFestivalDuration(new FestivalDuration(startDate, endDate)); // when & then assertDoesNotThrow(() -> validator.validate(축제)); @@ -114,7 +116,7 @@ class 축제에_등록된_공연이_없을때 { // given LocalDate startDate = festivalStartDate.plusDays(1); LocalDate endDate = festivalEndDate; - 축제.changeDate(startDate, endDate); + 축제.changeFestivalDuration(new FestivalDuration(startDate, endDate)); // when & then assertDoesNotThrow(() -> validator.validate(축제)); @@ -125,7 +127,7 @@ class 축제에_등록된_공연이_없을때 { // given LocalDate startDate = festivalStartDate; LocalDate endDate = festivalEndDate.minusDays(1); - 축제.changeDate(startDate, endDate); + 축제.changeFestivalDuration(new FestivalDuration(startDate, endDate)); // when & then assertDoesNotThrow(() -> validator.validate(축제)); diff --git a/backend/src/test/java/com/festago/support/fixture/FestivalFixture.java b/backend/src/test/java/com/festago/support/fixture/FestivalFixture.java index 85e3be6e5..4e9da3f22 100644 --- a/backend/src/test/java/com/festago/support/fixture/FestivalFixture.java +++ b/backend/src/test/java/com/festago/support/fixture/FestivalFixture.java @@ -1,6 +1,7 @@ package com.festago.support.fixture; import com.festago.festival.domain.Festival; +import com.festago.festival.domain.FestivalDuration; import com.festago.school.domain.School; import java.time.LocalDate; @@ -51,6 +52,7 @@ public FestivalFixture school(School school) { } public Festival build() { - return new Festival(id, uniqueValue("페스타고 대학교 축제", name), startDate, endDate, posterImageUrl, school); + return new Festival(id, uniqueValue("페스타고 대학교 축제", name), new FestivalDuration(startDate, endDate), + posterImageUrl, school); } } From 1d341814344e8a35357ec60f812a21ae5ec1b961 Mon Sep 17 00:00:00 2001 From: Seokjin Jeon Date: Sun, 21 Apr 2024 01:17:57 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[BE]=20refactor:=20Logback=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=8A=AC=EB=9E=99=EC=9C=BC=EB=A1=9C=20=EC=95=8C?= =?UTF-8?q?=EB=9E=8C=EC=9D=84=20=EB=B3=B4=EB=82=B4=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=EC=9D=84=20=EC=A0=9C=EA=B1=B0=ED=95=98=EA=B3=A0,=20Er?= =?UTF-8?q?rorLoggerConfig=EB=A5=BC=20=EC=82=AD=EC=A0=9C=ED=95=9C=EB=8B=A4?= =?UTF-8?q?.=20(#875)=20(#878)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: logback Slack 알람 기능 제거 * refactor: ErrorLoggerConfig 삭제 * feat: 서브모듈 업데이트 - 슬랙 웹훅 제거 --- .../common/aop/LogRequestBodyAspect.java | 13 +++++------- .../handler/GlobalExceptionHandler.java | 21 +++++++------------ .../com/festago/config/ErrorLoggerConfig.java | 15 ------------- backend/src/main/resources/config | 2 +- backend/src/main/resources/logback-spring.xml | 8 ------- .../logs/slack/slack-error-appender.xml | 20 ------------------ .../logs/slack/slack-warn-appender.xml | 20 ------------------ .../com/festago/support/CustomWebMvcTest.java | 4 +--- 8 files changed, 15 insertions(+), 88 deletions(-) delete mode 100644 backend/src/main/java/com/festago/config/ErrorLoggerConfig.java delete mode 100644 backend/src/main/resources/logs/slack/slack-error-appender.xml delete mode 100644 backend/src/main/resources/logs/slack/slack-warn-appender.xml diff --git a/backend/src/main/java/com/festago/common/aop/LogRequestBodyAspect.java b/backend/src/main/java/com/festago/common/aop/LogRequestBodyAspect.java index 205d4d6b0..8efb02a71 100644 --- a/backend/src/main/java/com/festago/common/aop/LogRequestBodyAspect.java +++ b/backend/src/main/java/com/festago/common/aop/LogRequestBodyAspect.java @@ -13,7 +13,6 @@ import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; -import org.slf4j.Logger; import org.slf4j.event.Level; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; @@ -31,14 +30,12 @@ public class LogRequestBodyAspect { private final Map> loggerMap = new EnumMap<>(Level.class); private final ObjectMapper objectMapper; - private final Logger errorLogger; - public LogRequestBodyAspect(ObjectMapper objectMapper, Logger errorLogger) { + public LogRequestBodyAspect(ObjectMapper objectMapper) { this.objectMapper = objectMapper; - this.errorLogger = errorLogger; - loggerMap.put(Level.INFO, this.errorLogger::info); - loggerMap.put(Level.WARN, this.errorLogger::warn); - loggerMap.put(Level.ERROR, this.errorLogger::error); + loggerMap.put(Level.INFO, log::info); + loggerMap.put(Level.WARN, log::warn); + loggerMap.put(Level.ERROR, log::error); } @Around("@annotation(LogRequestBody)") @@ -49,7 +46,7 @@ public Object handleAll(ProceedingJoinPoint pjp) throws Throwable { Level level = annotation.level(); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - if (attributes == null || !errorLogger.isEnabledForLevel(level)) { + if (attributes == null || !log.isEnabledForLevel(level)) { return pjp.proceed(); } HttpServletRequest request = attributes.getRequest(); diff --git a/backend/src/main/java/com/festago/common/handler/GlobalExceptionHandler.java b/backend/src/main/java/com/festago/common/handler/GlobalExceptionHandler.java index 5ef69d696..0d314d4d3 100644 --- a/backend/src/main/java/com/festago/common/handler/GlobalExceptionHandler.java +++ b/backend/src/main/java/com/festago/common/handler/GlobalExceptionHandler.java @@ -16,6 +16,7 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; @@ -31,6 +32,7 @@ @RequiredArgsConstructor public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { + private static final Logger log = LoggerFactory.getLogger("ErrorLogger"); private static final String LOG_FORMAT_INFO = "\n[🔵INFO] - ({} {})\n(id: {}, role: {})\n{}\n {}: {}"; private static final String LOG_FORMAT_WARN = "\n[🟠WARN] - ({} {})\n(id: {}, role: {})"; private static final String LOG_FORMAT_ERROR = "\n[🔴ERROR] - ({} {})\n(id: {}, role: {})"; @@ -60,7 +62,6 @@ public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { */ private final AuthenticateContext authenticateContext; - private final Logger errorLogger; @ExceptionHandler(InvalidMediaTypeException.class) public ResponseEntity handle(InvalidMediaTypeException e) { @@ -133,23 +134,17 @@ protected ResponseEntity handleMethodArgumentNotValid( } private void logInfo(FestaGoException e, HttpServletRequest request) { - if (errorLogger.isInfoEnabled()) { - errorLogger.info(LOG_FORMAT_INFO, request.getMethod(), request.getRequestURI(), authenticateContext.getId(), - authenticateContext.getRole(), e.getErrorCode(), e.getClass().getName(), e.getMessage()); - } + log.info(LOG_FORMAT_INFO, request.getMethod(), request.getRequestURI(), authenticateContext.getId(), + authenticateContext.getRole(), e.getErrorCode(), e.getClass().getName(), e.getMessage()); } private void logWarn(FestaGoException e, HttpServletRequest request) { - if (errorLogger.isWarnEnabled()) { - errorLogger.warn(LOG_FORMAT_WARN, request.getMethod(), request.getRequestURI(), - authenticateContext.getId(), authenticateContext.getRole(), e); - } + log.warn(LOG_FORMAT_WARN, request.getMethod(), request.getRequestURI(), + authenticateContext.getId(), authenticateContext.getRole(), e); } private void logError(Exception e, HttpServletRequest request) { - if (errorLogger.isErrorEnabled()) { - errorLogger.error(LOG_FORMAT_ERROR, request.getMethod(), request.getRequestURI(), - authenticateContext.getId(), authenticateContext.getRole(), e); - } + log.error(LOG_FORMAT_ERROR, request.getMethod(), request.getRequestURI(), + authenticateContext.getId(), authenticateContext.getRole(), e); } } diff --git a/backend/src/main/java/com/festago/config/ErrorLoggerConfig.java b/backend/src/main/java/com/festago/config/ErrorLoggerConfig.java deleted file mode 100644 index d0ec785df..000000000 --- a/backend/src/main/java/com/festago/config/ErrorLoggerConfig.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.festago.config; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class ErrorLoggerConfig { - - @Bean - public Logger errorLogger() { - return LoggerFactory.getLogger("ErrorLogger"); - } -} diff --git a/backend/src/main/resources/config b/backend/src/main/resources/config index 73c3c51a0..808a39ab1 160000 --- a/backend/src/main/resources/config +++ b/backend/src/main/resources/config @@ -1 +1 @@ -Subproject commit 73c3c51a0b3b1cdb63c750ee18e9ad33973d4d86 +Subproject commit 808a39ab1f8c51672dd1a3b8cc5d1f1643679023 diff --git a/backend/src/main/resources/logback-spring.xml b/backend/src/main/resources/logback-spring.xml index 1e0713bc2..8454df8e3 100644 --- a/backend/src/main/resources/logback-spring.xml +++ b/backend/src/main/resources/logback-spring.xml @@ -20,20 +20,17 @@ - - - @@ -44,22 +41,17 @@ - - - - - diff --git a/backend/src/main/resources/logs/slack/slack-error-appender.xml b/backend/src/main/resources/logs/slack/slack-error-appender.xml deleted file mode 100644 index 3a423d95c..000000000 --- a/backend/src/main/resources/logs/slack/slack-error-appender.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - ${WEBHOOK_URL} - - ${FILE_LOG_PATTERN} - - true - - - - - - ERROR - ACCEPT - DENY - - - diff --git a/backend/src/main/resources/logs/slack/slack-warn-appender.xml b/backend/src/main/resources/logs/slack/slack-warn-appender.xml deleted file mode 100644 index f2ad7079b..000000000 --- a/backend/src/main/resources/logs/slack/slack-warn-appender.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - ${WEBHOOK_URL} - - ${FILE_LOG_PATTERN} - - true - - - - - - WARN - ACCEPT - DENY - - - diff --git a/backend/src/test/java/com/festago/support/CustomWebMvcTest.java b/backend/src/test/java/com/festago/support/CustomWebMvcTest.java index 03b00c308..42063b6cb 100644 --- a/backend/src/test/java/com/festago/support/CustomWebMvcTest.java +++ b/backend/src/test/java/com/festago/support/CustomWebMvcTest.java @@ -1,7 +1,6 @@ package com.festago.support; import com.festago.common.aop.ValidPageableAspect; -import com.festago.config.ErrorLoggerConfig; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -12,8 +11,7 @@ @EnableAspectJAutoProxy @WebMvcTest -@Import({TestAuthConfig.class, ErrorLoggerConfig.class, MockAllServiceBeanFactoryPostProcessor.class, - ValidPageableAspect.class}) +@Import({TestAuthConfig.class, MockAllServiceBeanFactoryPostProcessor.class, ValidPageableAspect.class}) @Retention(RetentionPolicy.RUNTIME) @TestExecutionListeners(value = {MockAuthTestExecutionListener.class, ResetMockTestExecutionListener.class}, mergeMode = MergeMode.MERGE_WITH_DEFAULTS)