Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public void updateSemester() {

public boolean validateSemester(CoopSemester coopSemester) {
LocalDate today = LocalDate.now(clock);
return today.isAfter(coopSemester.getFromDate()) && today.isBefore(coopSemester.getToDate());
return !today.isBefore(coopSemester.getFromDate()) && !today.isAfter(coopSemester.getToDate())
&& !coopSemester.getCoopShops().isEmpty();
Comment on lines +116 to +117

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A

데이터가 없으면, 학기 전환 스케줄러에서 학기 전환을 막는 것으로 이해를 했습니다. 이해한 내용이 맞다면 학기가 전환이 되지 않아 이전 학기 시간표가 나오게 될 거 같은데, 이렇게 해도 되는지는 코인 정책 상으로 확인해봐야할 거 같아요.

방어 로직보다는 서비스에 영향이 가기 때문에, 오히려 저는 조회하는 시점에 해당 학기 생협 시간표 정보가 없다면 404를 던지는 것이 아니라 빈 리스트를 내리는 방법도 있을 거 같아요. 이전 학기의 정보를 확인해서 혼동이 생기는 것과 데이터가 없는 거 둘 중 하나를 택하라면 저는 후자를 생각할 거 같습니다. 이 부분은 프로젝트 참여 인원들과 함께 이야기 나눠보는 게 좋을 거 같아요 !

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

말씀 감사합니다!
예전 학기 정보를 보여주는 것보다 빈 리스트가 낫다라는 의견이 맞는거 같습니다.

다만 이걸 제대로 하려면 "학기 전환을 배치로 미리 정해두는 방식" 자체를
"조회 시점에 오늘에 맞는 학기를 그때그때 계산하는 방식"으로 바꿔야 할 것 같아서,
이번 PR 범위보다 큰 변경이 될 것 같습니다.
일단 이번 PR은 그대로 내버려두고 다음주에 트랙 주간회의 이후 다른 트랙분들과 이야기 나눠보는게 좋을거 같아요!

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package in.koreatech.koin.acceptance.domain;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
Expand All @@ -12,6 +13,7 @@
import in.koreatech.koin.acceptance.AcceptanceTest;
import in.koreatech.koin.acceptance.fixture.CoopShopAcceptanceFixture;
import in.koreatech.koin.domain.coopshop.service.CoopShopService;
import in.koreatech.koin.global.exception.custom.DataNotFoundException;

class CoopShopApiTest extends AcceptanceTest {

Expand Down Expand Up @@ -131,4 +133,12 @@ void setUp() {
}
"""));
}

@Test
void 다음_학기에_매장_데이터가_없으면_전환하지_않는다() throws Exception {
coopShopFixture._23_겨울학기_매장없음();

assertThatThrownBy(() -> coopShopService.updateSemester())
.isInstanceOf(DataNotFoundException.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,17 @@ public CoopShopAcceptanceFixture(
return coopSemesterRepository.save(coopSemester);
}

public CoopSemester _23_겨울학기_매장없음() {
var coopSemester = coopSemesterRepository.save(
CoopSemester.builder()
.semester("23-겨울학기")
.fromDate(LocalDate.of(2023, 12, 21))
.toDate(LocalDate.of(2024, 2, 28))
.build()
);
return coopSemesterRepository.save(coopSemester);
}

public CoopName 학생식당() {
return coopNameRepository.save(
CoopName.builder()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package in.koreatech.koin.unit.domain.coopshop;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.when;

import java.time.Clock;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.List;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import in.koreatech.koin.domain.coopshop.model.CoopName;
import in.koreatech.koin.domain.coopshop.model.CoopSemester;
import in.koreatech.koin.domain.coopshop.model.CoopShop;
import in.koreatech.koin.domain.coopshop.repository.CoopNameRepository;
import in.koreatech.koin.domain.coopshop.repository.CoopOpenRepository;
import in.koreatech.koin.domain.coopshop.repository.CoopSemesterRepository;
import in.koreatech.koin.domain.coopshop.repository.CoopShopRepository;
import in.koreatech.koin.domain.coopshop.service.CoopShopService;
import in.koreatech.koin.global.exception.custom.DataNotFoundException;

@ExtendWith(MockitoExtension.class)
class CoopShopServiceTest {

private CoopShopService coopShopService;

@Mock
private CoopShopRepository coopShopRepository;

@Mock
private CoopOpenRepository coopOpenRepository;

@Mock
private CoopSemesterRepository coopSemesterRepository;

@Mock
private CoopNameRepository coopNameRepository;

private final Clock clock = Clock.fixed(
Instant.parse("2026-09-18T00:05:00Z"),
ZoneId.of("Asia/Seoul")
);

@BeforeEach
void setUp() {
coopShopService = new CoopShopService(
clock, coopShopRepository, coopOpenRepository, coopSemesterRepository, coopNameRepository
);
}

private CoopSemester 학기(String semester, LocalDate fromDate, LocalDate toDate, boolean 매장있음) {
CoopSemester coopSemester = CoopSemester.of(semester, fromDate, toDate);
if (매장있음) {
CoopShop coopShop = CoopShop.builder()
.coopName(CoopName.builder().name("학생식당").build())
.location("학생회관 1층")
.phone("041-000-0000")
.build();
coopSemester.replaceCoopShops(List.of(coopShop));
}
return coopSemester;
}

@Test
@DisplayName("학기 시작일 당일에도 유효한 학기로 판단한다")
void 학기_시작일_당일에도_유효하다() {
CoopSemester currentSemester = 학기("26-1학기", LocalDate.of(2026, 3, 3), LocalDate.of(2026, 6, 19), true);
CoopSemester todayStartSemester = 학기("26-2학기", LocalDate.of(2026, 9, 18), LocalDate.of(2026, 12, 18), true);
when(coopSemesterRepository.getByIsApplied(true)).thenReturn(currentSemester);
when(coopSemesterRepository.getTopByOrderByToDateDesc()).thenReturn(todayStartSemester);

coopShopService.updateSemester();

assertThat(todayStartSemester.isApplied()).isTrue();
}

@Test
@DisplayName("현재 적용된 학기가 아직 유효하면 전환하지 않는다")
void 현재_학기가_유효하면_전환하지_않는다() {
CoopSemester currentSemester = 학기("26-2학기", LocalDate.of(2026, 9, 1), LocalDate.of(2026, 12, 18), true);
currentSemester.updateApply(true);
when(coopSemesterRepository.getByIsApplied(true)).thenReturn(currentSemester);

coopShopService.updateSemester();

assertThat(currentSemester.isApplied()).isTrue();
}

@Test
@DisplayName("다음 학기에 매장 데이터가 없으면 전환을 보류하고 예외를 던진다")
void 다음_학기에_매장이_없으면_전환하지_않는다() {
CoopSemester expiredSemester = 학기("26-1학기", LocalDate.of(2026, 3, 3), LocalDate.of(2026, 6, 19), true);
CoopSemester emptyNextSemester = 학기("26-2학기", LocalDate.of(2026, 9, 1), LocalDate.of(2026, 12, 18), false);
when(coopSemesterRepository.getByIsApplied(true)).thenReturn(expiredSemester);
when(coopSemesterRepository.getTopByOrderByToDateDesc()).thenReturn(emptyNextSemester);

assertThatThrownBy(() -> coopShopService.updateSemester())
.isInstanceOf(DataNotFoundException.class)
.hasMessageContaining("해당 학기가 존재하지 않습니다");
}

@Test
@DisplayName("다음 학기에 매장 데이터가 있으면 정상적으로 전환된다")
void 다음_학기에_매장이_있으면_전환된다() {
CoopSemester expiredSemester = 학기("26-1학기", LocalDate.of(2026, 3, 3), LocalDate.of(2026, 6, 19), true);
CoopSemester nextSemester = 학기("26-2학기", LocalDate.of(2026, 9, 1), LocalDate.of(2026, 12, 18), true);
when(coopSemesterRepository.getByIsApplied(true)).thenReturn(expiredSemester);
when(coopSemesterRepository.getTopByOrderByToDateDesc()).thenReturn(nextSemester);

coopShopService.updateSemester();

assertThat(nextSemester.isApplied()).isTrue();
}
}
Loading