package sgis.surveysystem.service; import sgis.surveysystem.domain.Survey; import sgis.surveysystem.mapper.SurveyMapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; // Optional 클래스 임포트 import java.util.UUID; /** * 설문(Survey) 관련 비즈니스 로직을 처리하는 서비스 클래스. * MyBatis Mapper를 통해 데이터베이스와 상호작용합니다. */ @Service @RequiredArgsConstructor // Lombok을 사용하여 final 필드를 인자로 받는 생성자를 자동 생성합니다. (의존성 주입) @Transactional // 클래스 레벨에 트랜잭션 설정을 적용합니다. public class SurveyService { private final SurveyMapper surveyMapper; /** * 새로운 설문을 생성합니다. * 설문 ID는 애플리케이션에서 UUID를 생성하여 할당합니다. * * @param surveyTitle 설문 제목 * @param surveyDescription 설문 상세 설명 * @param startDate 설문 시작 일시 * @param endDate 설문 종료 일시 * @return 생성된 Survey 객체 */ public Survey createSurvey(String surveyTitle, String surveyDescription, LocalDateTime startDate, LocalDateTime endDate) { // 애플리케이션에서 새로운 UUID를 생성하여 설문 ID로 사용합니다. // 데이터베이스의 DEFAULT gen_random_uuid() 설정과 무관하게 동작합니다. Survey survey = Survey.builder() .surveyId(UUID.randomUUID()) .surveyTitle(surveyTitle) .surveyDescription(surveyDescription) .createdAt(LocalDateTime.now()) // 현재 시각으로 생성일 설정 .updatedAt(LocalDateTime.now()) // 현재 시각으로 수정일 설정 .isActive(true) // 기본적으로 활성화 상태로 설정 .startDate(startDate) .endDate(endDate) .build(); surveyMapper.insertSurvey(survey); // Mapper를 통해 데이터베이스에 설문 정보 삽입 return survey; } /** * 모든 설문 목록을 조회합니다. * 읽기 전용 트랜잭션으로 설정하여 성능을 최적화합니다. * * @return 모든 Survey 객체 리스트 */ @Transactional(readOnly = true) public List getAllSurveys() { return surveyMapper.findAllSurveys(); // Mapper를 통해 모든 설문 조회 } /** * 특정 ID의 설문을 조회합니다. * 읽기 전용 트랜잭션으로 설정합니다. * * @param surveyId 설문 고유 ID * @return 조회된 Survey 객체 * @throws NoSuchElementException 해당 ID의 설문이 데이터베이스에 없을 경우 발생 */ @Transactional(readOnly = true) public Survey getSurveyById(UUID surveyId) { // Mapper에서 직접 Survey 객체를 반환하도록 변경했으므로, Optional.ofNullable()을 사용합니다. return Optional.ofNullable(surveyMapper.findSurveyById(surveyId)) .orElseThrow(() -> new NoSuchElementException("Survey not found with ID: " + surveyId)); // 없을 경우 예외 발생 } /** * 설문 정보를 업데이트합니다. * 업데이트 전에 해당 설문이 존재하는지 확인합니다. * * @param surveyId 업데이트할 설문의 고유 ID * @param surveyTitle 새로운 설문 제목 * @param surveyDescription 새로운 설문 설명 * @param isActive 설문 활성화 여부 * @param startDate 새로운 설문 시작 일시 * @param endDate 새로운 설문 종료 일시 * @return 업데이트된 Survey 객체 (업데이트 후 다시 조회하여 최신 상태 반환) * @throws NoSuchElementException 해당 ID의 설문이 없을 경우 */ public Survey updateSurvey(UUID surveyId, String surveyTitle, String surveyDescription, Boolean isActive, LocalDateTime startDate, LocalDateTime endDate) { // 업데이트할 설문이 존재하는지 먼저 확인합니다. getSurveyById(surveyId); // 업데이트할 필드들을 포함하는 Survey 객체를 생성합니다. // MyBatis는 이 객체의 필드 값을 사용하여 SQL 쿼리의 파라미터를 채웁니다. Survey survey = Survey.builder() .surveyId(surveyId) // 업데이트 대상 설문 ID .surveyTitle(surveyTitle) .surveyDescription(surveyDescription) .isActive(isActive) .startDate(startDate) .endDate(endDate) .updatedAt(LocalDateTime.now()) // 업데이트 시각을 현재로 갱신 .build(); surveyMapper.updateSurvey(survey); // Mapper를 통해 설문 정보 업데이트 // 업데이트된 최신 정보를 데이터베이스에서 다시 조회하여 반환합니다. return getSurveyById(surveyId); } /** * 특정 ID의 설문을 삭제합니다. * 삭제 전에 해당 설문이 존재하는지 확인합니다. * * @param surveyId 삭제할 설문의 고유 ID * @throws NoSuchElementException 해당 ID의 설문이 없을 경우 */ public void deleteSurvey(UUID surveyId) { // 삭제할 설문이 존재하는지 먼저 확인합니다. getSurveyById(surveyId); surveyMapper.deleteSurvey(surveyId); // Mapper를 통해 설문 삭제 } /** * 특정 ID의 설문을 비활성화합니다. * 비활성화 전에 해당 설문이 존재하는지 확인합니다. * * @param surveyId 비활성화할 설문의 고유 ID * @return 비활성화된 Survey 객체 (업데이트 후 다시 조회하여 최신 상태 반환) * @throws NoSuchElementException 해당 ID의 설문이 없을 경우 */ public Survey deactivateSurvey(UUID surveyId) { getSurveyById(surveyId); // 존재 여부 확인 surveyMapper.updateSurveyStatus(surveyId, false); // Mapper를 통해 설문 상태 업데이트 return getSurveyById(surveyId); // 업데이트된 상태로 반환 } }