feat: 설문 back-end 코드 추가 건
parent
94fc429640
commit
f0f09432c3
|
|
@ -25,7 +25,6 @@
|
|||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v8.5 (2)">
|
||||
|
|
@ -33,9 +32,9 @@
|
|||
<attribute name="owner.project.facets" value="jst.web"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.8.0_251">
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="owner.project.facets" value="java"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
|
|
|
|||
2
list.txt
2
list.txt
|
|
@ -13,3 +13,5 @@ src\main\webapp\WEB-INF\jsp\sgis\map\mapInformation\sichudanNew.jsp
|
|||
src\main\webapp\com\css\cross-section.css
|
||||
src\main\webapp\com\js\cross-section.js
|
||||
src\main\resources\egovframework\mapper\sgis\map\MapMainMapper.xml
|
||||
src\main\webapp\WEB-INF\jsp\sgis\map\mapInformation\boreholeLog.jsp
|
||||
src\main\webapp\WEB-INF\jsp\sgis\surveysystem\createSurvey.jsp
|
||||
5
pom.xml
5
pom.xml
|
|
@ -306,6 +306,11 @@
|
|||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.12.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>2.12.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package sgis.board.typehandler;
|
||||
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
@MappedTypes(UUID.class)
|
||||
@MappedJdbcTypes(JdbcType.OTHER) // Or JdbcType.VARCHAR if storing as string in DB
|
||||
public class UUIDTypeHandler extends BaseTypeHandler<UUID> {
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
|
||||
ps.setString(i, parameter.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
String uuidString = rs.getString(columnName);
|
||||
return uuidString == null ? null : UUID.fromString(uuidString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
String uuidString = rs.getString(columnIndex);
|
||||
return uuidString == null ? null : UUID.fromString(uuidString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
String uuidString = cs.getString(columnIndex);
|
||||
return uuidString == null ? null : UUID.fromString(uuidString);
|
||||
}
|
||||
}
|
||||
|
|
@ -49,4 +49,6 @@ public interface MapMainMapper {
|
|||
EgovMap selectWebDownloadLog(Map<String, Object> params) throws Exception; // dhlee 사용자별 다운로드 요청한 개수를 얻어온다.
|
||||
|
||||
List<EgovMap> selectProjectList(Map<String, Object> params) throws Exception;
|
||||
|
||||
List<EgovMap> mapBoreholeLogHeader(Map<String, Object> params) throws Exception;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,4 +50,5 @@ public interface MapMainService {
|
|||
|
||||
List<EgovMap> selectProjectList(Map<String, Object> params) throws Exception; // dhlee
|
||||
|
||||
List<EgovMap> mapBoreholeLogList(Map<String, Object> params) throws Exception;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,4 +117,15 @@ public class MapMainServiceImpl implements MapMainService {
|
|||
public List<EgovMap> selectProjectList(Map<String, Object> params) throws Exception {
|
||||
return mapMainMapper.selectProjectList(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EgovMap> mapBoreholeLogList(Map<String, Object> params) throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
//String businessCode = String.valueOf(params.get("businessCode"));
|
||||
//String holeCode = String.valueOf(params.get("holeCode"));
|
||||
|
||||
List<EgovMap> mapBoreholeLogHeader = mapMainMapper.mapBoreholeLogHeader(params);
|
||||
|
||||
return mapBoreholeLogHeader;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -408,6 +408,31 @@ public class MapMainController extends BaseController {
|
|||
return responseJson;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/map/borehole-log.do")
|
||||
public String mapBoreholeLog(ModelMap model, HttpServletRequest request, HttpServletResponse response, @RequestParam Map<String, Object> params) throws Exception {
|
||||
return "/sgis/map/mapInformation/boreholeLog";
|
||||
}
|
||||
|
||||
/**
|
||||
* 지반 주상도 생성에 필요한 정보를 얻는다.
|
||||
* @param model
|
||||
* @param request
|
||||
* @param response
|
||||
* @param params
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@RequestMapping(value = "/map/borehole-log/list.do", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
|
||||
@ResponseBody
|
||||
public JSONObject mapBoreholeLogList(ModelMap model, HttpServletRequest request, HttpServletResponse response, @RequestParam Map<String, Object> params) throws Exception {
|
||||
StringBuffer sb = request.getRequestURL();
|
||||
String url = sb.substring(0, sb.lastIndexOf("/"));
|
||||
|
||||
JSONObject responseJson = new JSONObject();
|
||||
responseJson.put("list", mapMainService.mapBoreholeLogList(params));
|
||||
return responseJson;
|
||||
}
|
||||
|
||||
public JSONObject getSectionData(String code) throws Exception {
|
||||
|
||||
code = code.trim();
|
||||
|
|
@ -422,6 +447,10 @@ public class MapMainController extends BaseController {
|
|||
|
||||
|
||||
EgovMap general = mapMainService.getGeneralData(params);
|
||||
|
||||
if( general == null ) {
|
||||
// 예외처리 추가하기
|
||||
}
|
||||
String[] values = String.valueOf(general.get("vlu")).split("\\|");
|
||||
|
||||
JSONObject resultJson = new JSONObject();
|
||||
|
|
@ -442,7 +471,11 @@ public class MapMainController extends BaseController {
|
|||
resultJson.put("LL", position);
|
||||
|
||||
resultJson.put("PNAME", values[7]);
|
||||
if( 8 < values.length && values[8] != null ) {
|
||||
resultJson.put("WATER", values[8]);
|
||||
} else {
|
||||
resultJson.put("WATER", "");
|
||||
}
|
||||
|
||||
if (values.length == 10) {
|
||||
resultJson.put("PCOM", values[9]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
package sgis.surveysystem.config;
|
||||
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* java.time.LocalDateTime 객체와 JDBC Timestamp (PostgreSQL TIMESTAMP WITH TIME ZONE) 컬럼 간의 매핑을 처리하는 MyBatis TypeHandler.
|
||||
*/
|
||||
@MappedJdbcTypes(JdbcType.TIMESTAMP) // 이 TypeHandler가 처리할 JDBC 타입
|
||||
@MappedTypes(LocalDateTime.class) // 이 TypeHandler가 처리할 Java 타입
|
||||
public class LocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime> {
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType) throws SQLException {
|
||||
// LocalDateTime을 JDBC Timestamp로 변환하여 PreparedStatement에 설정
|
||||
ps.setTimestamp(i, Timestamp.valueOf(parameter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
// ResultSet에서 컬럼 이름으로 Timestamp 값을 가져와 LocalDateTime으로 변환
|
||||
Timestamp ts = rs.getTimestamp(columnName);
|
||||
return (ts != null) ? ts.toLocalDateTime() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
// ResultSet에서 컬럼 인덱스로 Timestamp 값을 가져와 LocalDateTime으로 변환
|
||||
Timestamp ts = rs.getTimestamp(columnIndex);
|
||||
return (ts != null) ? ts.toLocalDateTime() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
// CallableStatement에서 Timestamp 값을 가져와 LocalDateTime으로 변환
|
||||
Timestamp ts = cs.getTimestamp(columnIndex);
|
||||
return (ts != null) ? ts.toLocalDateTime() : null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package sgis.surveysystem.config;
|
||||
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.MappedJdbcTypes;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* java.util.UUID 객체와 PostgreSQL의 UUID (JDBC Type.OTHER) 컬럼 간의 매핑을 처리하는 MyBatis TypeHandler.
|
||||
*/
|
||||
@MappedJdbcTypes(JdbcType.OTHER) // 이 TypeHandler가 처리할 JDBC 타입 (PostgreSQL의 UUID는 OTHER로 인식됨)
|
||||
@MappedTypes(UUID.class) // 이 TypeHandler가 처리할 Java 타입
|
||||
public class UUIDTypeHandler extends BaseTypeHandler<UUID> {
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
|
||||
// Java UUID 객체를 JDBC PreparedStatement에 설정할 때
|
||||
// PostgreSQL의 UUID 타입은 String으로 변환하여 설정하거나, setObject(UUID)를 직접 사용할 수 있습니다.
|
||||
// setString이 더 안전하고 호환성이 높습니다.
|
||||
ps.setString(i, parameter.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
// ResultSet에서 컬럼 이름으로 값을 가져와 Java UUID 객체로 변환할 때
|
||||
String uuidString = rs.getString(columnName);
|
||||
return (uuidString != null) ? UUID.fromString(uuidString) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
// ResultSet에서 컬럼 인덱스로 값을 가져와 Java UUID 객체로 변환할 때
|
||||
String uuidString = rs.getString(columnIndex);
|
||||
return (uuidString != null) ? UUID.fromString(uuidString) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
// CallableStatement에서 값을 가져와 Java UUID 객체로 변환할 때
|
||||
String uuidString = cs.getString(columnIndex);
|
||||
return (uuidString != null) ? UUID.fromString(uuidString) : null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package sgis.surveysystem.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* 관리자 설문 페이지를 위한 컨트롤러.
|
||||
* JSP 뷰 파일을 반환합니다.
|
||||
*/
|
||||
@Controller // 뷰 이름을 반환하는 컨트롤러임을 명시
|
||||
@RequestMapping("/admin/survey") // 이 컨트롤러의 기본 URL 경로
|
||||
public class AdminSurveyPageController {
|
||||
|
||||
/**
|
||||
* 설문 생성 폼 페이지를 표시합니다.
|
||||
* 웹 브라우저에서 http://localhost:8080/your-app-context/admin/survey/create 로 접근 시 이 메서드가 호출됩니다.
|
||||
* (your-app-context는 웹 애플리케이션의 컨텍스트 경로입니다. 예: /sgis)
|
||||
*
|
||||
* @return JSP 파일의 논리적 경로 (ViewResolver에 의해 실제 경로로 변환됨)
|
||||
*/
|
||||
@GetMapping("/create.do")
|
||||
public String showCreateSurveyForm() {
|
||||
// ViewResolver 설정에 따라 다음 경로의 JSP 파일을 찾게 됩니다:
|
||||
// /WEB-INF/jsp/ + sgis/surveysystem/createSurvey + .jsp
|
||||
return "sgis/surveysystem/createSurvey";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
package sgis.surveysystem.controller;
|
||||
|
||||
import sgis.surveysystem.dto.QuestionCreateRequest;
|
||||
import sgis.surveysystem.dto.QuestionResponse;
|
||||
import sgis.surveysystem.dto.QuestionUpdateRequest;
|
||||
import sgis.surveysystem.dto.QuestionOptionResponse; // QuestionResponse에서 옵션을 포함하기 위해 필요
|
||||
import sgis.surveysystem.service.QuestionService;
|
||||
import sgis.surveysystem.service.QuestionOptionService; // 문항 옵션을 가져오기 위해 주입
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 설문 문항(Question) 관련 HTTP 요청을 처리하는 REST 컨트롤러.
|
||||
* 문항 생성, 조회, 수정, 삭제 등의 API 엔드포인트를 제공합니다.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/questions")
|
||||
@RequiredArgsConstructor
|
||||
public class QuestionController {
|
||||
|
||||
private final QuestionService questionService;
|
||||
private final QuestionOptionService questionOptionService; // 객관식 문항의 옵션을 로드하기 위해 필요
|
||||
|
||||
/**
|
||||
* 새로운 설문 문항을 생성합니다. (HTTP POST)
|
||||
*
|
||||
* @param request Question 생성 요청 DTO
|
||||
* @return 생성된 문항 정보를 담은 응답 (HTTP 201 Created)
|
||||
*/
|
||||
@PostMapping
|
||||
public ResponseEntity<QuestionResponse> createQuestion(@RequestBody QuestionCreateRequest request) {
|
||||
QuestionResponse createdQuestion = QuestionResponse.from(
|
||||
questionService.createQuestion(
|
||||
request.getSurveyId(),
|
||||
request.getQuestionText(),
|
||||
request.getQuestionType(),
|
||||
request.getQuestionOrder(),
|
||||
request.getIsRequired()
|
||||
)
|
||||
);
|
||||
return new ResponseEntity<>(createdQuestion, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 설문에 속한 모든 문항을 조회합니다. (HTTP GET)
|
||||
* 문항 유형이 객관식인 경우, 해당 문항의 옵션도 함께 포함하여 반환합니다.
|
||||
*
|
||||
* @param surveyId 문항 목록을 조회할 설문 ID
|
||||
* @return 해당 설문의 모든 문항 정보를 담은 응답 리스트 (HTTP 200 OK)
|
||||
*/
|
||||
@GetMapping("/by-survey/{surveyId}")
|
||||
public ResponseEntity<List<QuestionResponse>> getQuestionsBySurveyId(@PathVariable UUID surveyId) {
|
||||
List<QuestionResponse> questions = questionService.getQuestionsBySurveyId(surveyId).stream()
|
||||
.map(question -> {
|
||||
QuestionResponse questionResponse = QuestionResponse.from(question);
|
||||
// 문항 유형이 객관식인 경우, 해당 문항의 옵션을 조회하여 DTO에 설정합니다.
|
||||
if (question.getQuestionType().startsWith("객관식")) {
|
||||
List<QuestionOptionResponse> options = questionOptionService.getOptionsByQuestionId(question.getQuestionId()).stream()
|
||||
.map(QuestionOptionResponse::from)
|
||||
.collect(Collectors.toList());
|
||||
questionResponse.setOptions(options); // QuestionResponse DTO에 옵션 리스트 설정
|
||||
}
|
||||
return questionResponse;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
return ResponseEntity.ok(questions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 문항을 조회합니다. (HTTP GET)
|
||||
* 문항 유형이 객관식인 경우, 해당 문항의 옵션도 함께 포함하여 반환합니다.
|
||||
*
|
||||
* @param questionId 조회할 문항의 고유 ID
|
||||
* @return 조회된 문항 정보를 담은 응답 (HTTP 200 OK)
|
||||
* 문항이 없을 경우 HTTP 404 Not Found 반환
|
||||
*/
|
||||
@GetMapping("/{questionId}")
|
||||
public ResponseEntity<QuestionResponse> getQuestionById(@PathVariable UUID questionId) {
|
||||
try {
|
||||
QuestionResponse question = QuestionResponse.from(questionService.getQuestionById(questionId));
|
||||
// 문항 유형이 객관식인 경우, 해당 문항의 옵션을 조회하여 DTO에 설정합니다.
|
||||
if (question.getQuestionType().startsWith("객관식")) {
|
||||
List<QuestionOptionResponse> options = questionOptionService.getOptionsByQuestionId(question.getQuestionId()).stream()
|
||||
.map(QuestionOptionResponse::from)
|
||||
.collect(Collectors.toList());
|
||||
question.setOptions(options); // QuestionResponse DTO에 옵션 리스트 설정
|
||||
}
|
||||
return ResponseEntity.ok(question);
|
||||
} catch (NoSuchElementException e) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 문항 정보를 업데이트합니다. (HTTP PUT)
|
||||
*
|
||||
* @param questionId 업데이트할 문항의 고유 ID
|
||||
* @param request Question 업데이트 요청 DTO
|
||||
* @return 업데이트된 문항 정보를 담은 응답 (HTTP 200 OK)
|
||||
* 문항이 없을 경우 HTTP 404 Not Found 반환
|
||||
*/
|
||||
@PutMapping("/{questionId}")
|
||||
public ResponseEntity<QuestionResponse> updateQuestion(@PathVariable UUID questionId, @RequestBody QuestionUpdateRequest request) {
|
||||
try {
|
||||
QuestionResponse updatedQuestion = QuestionResponse.from(
|
||||
questionService.updateQuestion(
|
||||
questionId,
|
||||
request.getQuestionText(),
|
||||
request.getQuestionType(),
|
||||
request.getQuestionOrder(),
|
||||
request.getIsRequired()
|
||||
)
|
||||
);
|
||||
return ResponseEntity.ok(updatedQuestion);
|
||||
} catch (NoSuchElementException e) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 문항을 삭제합니다. (HTTP DELETE)
|
||||
*
|
||||
* @param questionId 삭제할 문항의 고유 ID
|
||||
* @return 응답 본문 없이 HTTP 204 No Content 반환
|
||||
* 문항이 없을 경우 HTTP 404 Not Found 반환
|
||||
*/
|
||||
@DeleteMapping("/{questionId}")
|
||||
public ResponseEntity<Void> deleteQuestion(@PathVariable UUID questionId) {
|
||||
try {
|
||||
questionService.deleteQuestion(questionId);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
} catch (NoSuchElementException e) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
package sgis.surveysystem.controller;
|
||||
|
||||
import sgis.surveysystem.dto.QuestionOptionCreateRequest;
|
||||
import sgis.surveysystem.dto.QuestionOptionResponse;
|
||||
import sgis.surveysystem.dto.QuestionOptionUpdateRequest;
|
||||
import sgis.surveysystem.service.QuestionOptionService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 객관식 문항 선택지(QuestionOption) 관련 HTTP 요청을 처리하는 REST 컨트롤러.
|
||||
* 선택지 생성, 조회, 수정, 삭제 등의 API 엔드포인트를 제공합니다.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/question-options")
|
||||
@RequiredArgsConstructor
|
||||
public class QuestionOptionController {
|
||||
|
||||
private final QuestionOptionService questionOptionService;
|
||||
|
||||
/**
|
||||
* 새로운 객관식 문항 선택지를 생성합니다. (HTTP POST)
|
||||
*
|
||||
* @param request QuestionOption 생성 요청 DTO
|
||||
* @return 생성된 선택지 정보를 담은 응답 (HTTP 201 Created)
|
||||
*/
|
||||
@PostMapping
|
||||
public ResponseEntity<QuestionOptionResponse> createQuestionOption(@RequestBody QuestionOptionCreateRequest request) {
|
||||
QuestionOptionResponse createdOption = QuestionOptionResponse.from(
|
||||
questionOptionService.createQuestionOption(
|
||||
request.getQuestionId(),
|
||||
request.getOptionText(),
|
||||
request.getOptionOrder()
|
||||
)
|
||||
);
|
||||
return new ResponseEntity<>(createdOption, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 문항에 속한 모든 선택지를 조회합니다. (HTTP GET)
|
||||
*
|
||||
* @param questionId 선택지 목록을 조회할 문항 ID
|
||||
* @return 해당 문항의 모든 선택지 정보를 담은 응답 리스트 (HTTP 200 OK)
|
||||
*/
|
||||
@GetMapping("/by-question/{questionId}")
|
||||
public ResponseEntity<List<QuestionOptionResponse>> getOptionsByQuestionId(@PathVariable UUID questionId) {
|
||||
List<QuestionOptionResponse> options = questionOptionService.getOptionsByQuestionId(questionId).stream()
|
||||
.map(QuestionOptionResponse::from)
|
||||
.collect(Collectors.toList());
|
||||
return ResponseEntity.ok(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 선택지를 조회합니다. (HTTP GET)
|
||||
*
|
||||
* @param optionId 조회할 선택지의 고유 ID
|
||||
* @return 조회된 선택지 정보를 담은 응답 (HTTP 200 OK)
|
||||
* 선택지가 없을 경우 HTTP 404 Not Found 반환
|
||||
*/
|
||||
@GetMapping("/{optionId}")
|
||||
public ResponseEntity<QuestionOptionResponse> getQuestionOptionById(@PathVariable UUID optionId) {
|
||||
try {
|
||||
QuestionOptionResponse option = QuestionOptionResponse.from(questionOptionService.getQuestionOptionById(optionId));
|
||||
return ResponseEntity.ok(option);
|
||||
} catch (NoSuchElementException e) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 선택지 정보를 업데이트합니다. (HTTP PUT)
|
||||
*
|
||||
* @param optionId 업데이트할 선택지의 고유 ID
|
||||
* @param request QuestionOption 업데이트 요청 DTO
|
||||
* @return 업데이트된 선택지 정보를 담은 응답 (HTTP 200 OK)
|
||||
* 선택지가 없을 경우 HTTP 404 Not Found 반환
|
||||
*/
|
||||
@PutMapping("/{optionId}")
|
||||
public ResponseEntity<QuestionOptionResponse> updateQuestionOption(@PathVariable UUID optionId, @RequestBody QuestionOptionUpdateRequest request) {
|
||||
try {
|
||||
QuestionOptionResponse updatedOption = QuestionOptionResponse.from(
|
||||
questionOptionService.updateQuestionOption(
|
||||
optionId,
|
||||
request.getOptionText(),
|
||||
request.getOptionOrder()
|
||||
)
|
||||
);
|
||||
return ResponseEntity.ok(updatedOption);
|
||||
} catch (NoSuchElementException e) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 선택지를 삭제합니다. (HTTP DELETE)
|
||||
*
|
||||
* @param optionId 삭제할 선택지의 고유 ID
|
||||
* @return 응답 본문 없이 HTTP 204 No Content 반환
|
||||
* 선택지가 없을 경우 HTTP 404 Not Found 반환
|
||||
*/
|
||||
@DeleteMapping("/{optionId}")
|
||||
public ResponseEntity<Void> deleteQuestionOption(@PathVariable UUID optionId) {
|
||||
try {
|
||||
questionOptionService.deleteQuestionOption(optionId);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
} catch (NoSuchElementException e) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
package sgis.surveysystem.controller;
|
||||
|
||||
import sgis.surveysystem.dto.SurveyCreateRequest;
|
||||
import sgis.surveysystem.dto.SurveyResponse;
|
||||
import sgis.surveysystem.dto.SurveyUpdateRequest;
|
||||
import sgis.surveysystem.service.SurveyService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 설문(Survey) 관련 HTTP 요청을 처리하는 REST 컨트롤러.
|
||||
* 설문 생성, 조회, 수정, 삭제 등의 API 엔드포인트를 제공합니다.
|
||||
* 모든 요청은 .do 확장자로 끝나며, GET과 POST 메서드만 사용합니다.
|
||||
*/
|
||||
@RestController // RESTful 웹 서비스 컨트롤러임을 선언
|
||||
@RequestMapping("/api/surveys") // 기본 URL 경로 (이 부분은 .do를 포함하지 않음, 각 메서드에서 .do를 추가)
|
||||
@RequiredArgsConstructor // Lombok을 사용하여 final 필드를 인자로 받는 생성자 자동 생성 (SurveyService 주입)
|
||||
public class SurveyController {
|
||||
|
||||
private final SurveyService surveyService;
|
||||
|
||||
/**
|
||||
* 새로운 설문을 생성합니다. (HTTP POST)
|
||||
* 요청 본문에서 설문 정보를 받아 서비스를 통해 저장합니다.
|
||||
*
|
||||
* @param request Survey 생성 요청 DTO
|
||||
* @return 생성된 설문 정보를 담은 응답 (HTTP 201 Created)
|
||||
*/
|
||||
@PostMapping("/createSurvey.do") // POST 요청 처리, .do 확장자 추가
|
||||
public ResponseEntity<SurveyResponse> createSurvey(@RequestBody SurveyCreateRequest request) {
|
||||
// 서비스 계층의 createSurvey 메서드를 호출하여 설문을 생성합니다.
|
||||
// DTO의 정보를 서비스 메서드의 파라미터로 전달합니다.
|
||||
SurveyResponse createdSurvey = SurveyResponse.from(
|
||||
surveyService.createSurvey(
|
||||
request.getSurveyTitle(),
|
||||
request.getSurveyDescription(), // 수정: surveydescription() -> getSurveyDescription()
|
||||
request.getStartDate(),
|
||||
request.getEndDate()
|
||||
)
|
||||
);
|
||||
// 생성 성공 시 201 Created 상태 코드와 함께 생성된 설문 정보를 반환합니다.
|
||||
return new ResponseEntity<>(createdSurvey, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 모든 설문 목록을 조회합니다. (HTTP GET)
|
||||
*
|
||||
* @return 모든 설문 정보를 담은 응답 리스트 (HTTP 200 OK)
|
||||
*/
|
||||
@GetMapping("/getAllSurveys.do") // GET 요청 처리, .do 확장자 추가
|
||||
public ResponseEntity<List<SurveyResponse>> getAllSurveys() {
|
||||
// 서비스 계층에서 모든 설문을 조회하고, 각 설문 Entity를 SurveyResponse DTO로 변환합니다.
|
||||
List<SurveyResponse> surveys = surveyService.getAllSurveys().stream()
|
||||
.map(SurveyResponse::from)
|
||||
.collect(Collectors.toList());
|
||||
// 조회 성공 시 200 OK 상태 코드와 함께 설문 목록을 반환합니다.
|
||||
return ResponseEntity.ok(surveys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 설문을 조회합니다. (HTTP GET)
|
||||
* URL 경로 변수(PathVariable)를 통해 설문 ID를 받습니다.
|
||||
*
|
||||
* @param surveyId 조회할 설문의 고유 ID
|
||||
* @return 조회된 설문 정보를 담은 응답 (HTTP 200 OK)
|
||||
* 설문이 없을 경우 HTTP 404 Not Found 반환
|
||||
*/
|
||||
@GetMapping("/{surveyId}/getSurvey.do") // {surveyId}는 URL 경로의 변수, .do 확장자 추가
|
||||
public ResponseEntity<SurveyResponse> getSurveyById(@PathVariable UUID surveyId) {
|
||||
try {
|
||||
// 서비스 계층에서 ID로 설문을 조회하고, Entity를 SurveyResponse DTO로 변환합니다.
|
||||
SurveyResponse survey = SurveyResponse.from(surveyService.getSurveyById(surveyId));
|
||||
return ResponseEntity.ok(survey);
|
||||
} catch (NoSuchElementException e) {
|
||||
// 해당 ID의 설문을 찾을 수 없을 경우 404 Not Found 상태 코드를 반환합니다.
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 설문 정보를 업데이트합니다. (HTTP POST)
|
||||
* PUT 요청 대신 POST를 사용하며, URL 경로에 update 액션을 명시합니다.
|
||||
*
|
||||
* @param surveyId 업데이트할 설문의 고유 ID
|
||||
* @param request Survey 업데이트 요청 DTO
|
||||
* @return 업데이트된 설문 정보를 담은 응답 (HTTP 200 OK)
|
||||
* 설문이 없을 경우 HTTP 404 Not Found 반환
|
||||
*/
|
||||
@PostMapping("/{surveyId}/updateSurvey.do") // POST 요청으로 업데이트 처리, .do 확장자 추가
|
||||
public ResponseEntity<SurveyResponse> updateSurvey(@PathVariable UUID surveyId, @RequestBody SurveyUpdateRequest request) {
|
||||
try {
|
||||
// 서비스 계층의 updateSurvey 메서드를 호출하여 설문을 업데이트합니다.
|
||||
SurveyResponse updatedSurvey = SurveyResponse.from(
|
||||
surveyService.updateSurvey(
|
||||
surveyId,
|
||||
request.getSurveyTitle(),
|
||||
request.getSurveyDescription(), // 수정: surveydescription() -> getSurveyDescription()
|
||||
request.getIsActive(),
|
||||
request.getStartDate(),
|
||||
request.getEndDate()
|
||||
)
|
||||
);
|
||||
return ResponseEntity.ok(updatedSurvey);
|
||||
} catch (NoSuchElementException e) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 설문을 삭제합니다. (HTTP POST)
|
||||
* DELETE 요청 대신 POST를 사용하며, URL 경로에 delete 액션을 명시합니다.
|
||||
*
|
||||
* @param surveyId 삭제할 설문의 고유 ID
|
||||
* @return 응답 본문 없이 HTTP 204 No Content 반환
|
||||
* 설문이 없을 경우 HTTP 404 Not Found 반환
|
||||
*/
|
||||
@PostMapping("/{surveyId}/deleteSurvey.do") // POST 요청으로 삭제 처리, .do 확장자 추가
|
||||
public ResponseEntity<Void> deleteSurvey(@PathVariable UUID surveyId) {
|
||||
try {
|
||||
// 서비스 계층의 deleteSurvey 메서드를 호출하여 설문을 삭제합니다.
|
||||
surveyService.deleteSurvey(surveyId);
|
||||
// 삭제 성공 시 204 No Content 상태 코드를 반환합니다. (응답 본문 없음)
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
} catch (NoSuchElementException e) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 설문을 비활성화합니다. (HTTP POST)
|
||||
* PATCH 요청 대신 POST를 사용하며, URL 경로에 deactivate 액션을 명시합니다.
|
||||
*
|
||||
* @param surveyId 비활성화할 설문의 고유 ID
|
||||
* @return 비활성화된 설문 정보를 담은 응답 (HTTP 200 OK)
|
||||
* 설문이 없을 경우 HTTP 404 Not Found 반환
|
||||
*/
|
||||
@PostMapping("/{surveyId}/deactivateSurvey.do") // POST 요청으로 비활성화 처리, .do 확장자 추가
|
||||
public ResponseEntity<SurveyResponse> deactivateSurvey(@PathVariable UUID surveyId) {
|
||||
try {
|
||||
// 서비스 계층의 deactivateSurvey 메서드를 호출하여 설문을 비활성화합니다.
|
||||
SurveyResponse deactivatedSurvey = SurveyResponse.from(surveyService.deactivateSurvey(surveyId));
|
||||
return ResponseEntity.ok(deactivatedSurvey);
|
||||
} catch (NoSuchElementException e) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package sgis.surveysystem.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class Answer {
|
||||
private UUID answerId;
|
||||
private UUID responseId; // FK: tb_survey_responses.response_id
|
||||
private UUID questionId; // FK: tb_questions.question_id
|
||||
private String answerText;
|
||||
private UUID selectedOptionId; // FK: tb_question_options.option_id (단일 선택용)
|
||||
|
||||
@Builder
|
||||
public Answer(UUID answerId, UUID responseId, UUID questionId, String answerText, UUID selectedOptionId) {
|
||||
this.answerId = answerId;
|
||||
this.responseId = responseId;
|
||||
this.questionId = questionId;
|
||||
this.answerText = answerText;
|
||||
this.selectedOptionId = selectedOptionId;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package sgis.surveysystem.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class AnswerSelectedOption {
|
||||
private UUID answerId; // FK: tb_answers.answer_id (복합 PK의 일부)
|
||||
private UUID optionId; // FK: tb_question_options.option_id (복합 PK의 일부)
|
||||
|
||||
@Builder
|
||||
public AnswerSelectedOption(UUID answerId, UUID optionId) {
|
||||
this.answerId = answerId;
|
||||
this.optionId = optionId;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package sgis.surveysystem.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class Question {
|
||||
private UUID questionId;
|
||||
private UUID surveyId; // FK: tb_surveys.survey_id
|
||||
private String questionText;
|
||||
private String questionType;
|
||||
private Integer questionOrder;
|
||||
private Boolean isRequired;
|
||||
|
||||
@Builder
|
||||
public Question(UUID questionId, UUID surveyId, String questionText, String questionType, Integer questionOrder, Boolean isRequired) {
|
||||
this.questionId = questionId;
|
||||
this.surveyId = surveyId;
|
||||
this.questionText = questionText;
|
||||
this.questionType = questionType;
|
||||
this.questionOrder = questionOrder;
|
||||
this.isRequired = isRequired;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package sgis.surveysystem.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class QuestionOption {
|
||||
private UUID optionId;
|
||||
private UUID questionId; // FK: tb_questions.question_id
|
||||
private String optionText;
|
||||
private Integer optionOrder;
|
||||
|
||||
@Builder
|
||||
public QuestionOption(UUID optionId, UUID questionId, String optionText, Integer optionOrder) {
|
||||
this.optionId = optionId;
|
||||
this.questionId = questionId;
|
||||
this.optionText = optionText;
|
||||
this.optionOrder = optionOrder;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package sgis.surveysystem.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class Respondent {
|
||||
private UUID respondentId;
|
||||
private String userId;
|
||||
private String ipAddress; // INET 타입은 String으로 매핑 (MyBatis에서 별도 타입 핸들러 필요할 수 있음)
|
||||
private LocalDateTime responseStartAt;
|
||||
private LocalDateTime responseEndAt;
|
||||
|
||||
@Builder
|
||||
public Respondent(UUID respondentId, String userId, String ipAddress, LocalDateTime responseStartAt, LocalDateTime responseEndAt) {
|
||||
this.respondentId = respondentId;
|
||||
this.userId = userId;
|
||||
this.ipAddress = ipAddress;
|
||||
this.responseStartAt = responseStartAt;
|
||||
this.responseEndAt = responseEndAt;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package sgis.surveysystem.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter; // MyBatis는 매핑 시 Setter를 사용하기도 함
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter // MyBatis 매핑을 위해 필요할 수 있음
|
||||
@NoArgsConstructor // 기본 생성자
|
||||
@Builder
|
||||
public class Survey {
|
||||
private UUID surveyId;
|
||||
private String surveyTitle;
|
||||
private String surveyDescription;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private Boolean isActive;
|
||||
private LocalDateTime startDate;
|
||||
private LocalDateTime endDate;
|
||||
|
||||
@Builder // 빌더 패턴을 위한 어노테이션
|
||||
public Survey(UUID surveyId, String surveyTitle, String surveyDescription, LocalDateTime createdAt, LocalDateTime updatedAt, Boolean isActive, LocalDateTime startDate, LocalDateTime endDate) {
|
||||
this.surveyId = surveyId;
|
||||
this.surveyTitle = surveyTitle;
|
||||
this.surveyDescription = surveyDescription;
|
||||
this.createdAt = createdAt;
|
||||
this.updatedAt = updatedAt;
|
||||
this.isActive = isActive;
|
||||
this.startDate = startDate;
|
||||
this.endDate = endDate;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package sgis.surveysystem.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class SurveyResponse {
|
||||
private UUID responseId;
|
||||
private UUID surveyId; // FK: tb_surveys.survey_id
|
||||
private UUID respondentId; // FK: tb_respondents.respondent_id
|
||||
private LocalDateTime submittedAt;
|
||||
|
||||
@Builder
|
||||
public SurveyResponse(UUID responseId, UUID surveyId, UUID respondentId, LocalDateTime submittedAt) {
|
||||
this.responseId = responseId;
|
||||
this.surveyId = surveyId;
|
||||
this.respondentId = respondentId;
|
||||
this.submittedAt = submittedAt;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.Answer;
|
||||
import sgis.surveysystem.domain.AnswerSelectedOption; // 다중 선택 옵션 DTO 변환을 위해 필요
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
// 답변 생성 요청 DTO (단일/주관식/다중 선택 모두 커버)
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AnswerCreateRequest {
|
||||
private UUID responseId;
|
||||
private UUID questionId;
|
||||
private String answerText; // 단답형, 주관식용
|
||||
private UUID selectedOptionId; // 객관식 단일 선택용
|
||||
private List<UUID> selectedOptionIds; // 객관식 다중 선택용
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import sgis.surveysystem.domain.Answer;
|
||||
|
||||
//답변 응답 DTO (다중 선택 옵션 포함)
|
||||
@Getter
|
||||
@Setter // AnswerSelectedOptionResponse 리스트를 설정하기 위해 Setter 필요
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AnswerResponse {
|
||||
private UUID answerId;
|
||||
private UUID responseId;
|
||||
private UUID questionId;
|
||||
private String answerText;
|
||||
private UUID selectedOptionId;
|
||||
private List<AnswerSelectedOptionResponse> selectedOptions; // 다중 선택된 옵션 목록
|
||||
|
||||
public static AnswerResponse from(Answer answer) {
|
||||
if (answer == null) {
|
||||
return null;
|
||||
}
|
||||
return AnswerResponse.builder()
|
||||
.answerId(answer.getAnswerId())
|
||||
.responseId(answer.getResponseId())
|
||||
.questionId(answer.getQuestionId())
|
||||
.answerText(answer.getAnswerText())
|
||||
.selectedOptionId(answer.getSelectedOptionId())
|
||||
// selectedOptions는 서비스/컨트롤러에서 AnswerSelectedOptionService를 통해 채웁니다.
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
//다중 선택 옵션 추가 요청 DTO
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AnswerSelectedOptionCreateRequest {
|
||||
private UUID answerId; // 어떤 Answer에 속하는지
|
||||
private UUID optionId; // 선택된 옵션 ID
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.AnswerSelectedOption;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
|
||||
// 다중 선택 옵션 응답 DTO
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AnswerSelectedOptionResponse {
|
||||
private UUID answerId;
|
||||
private UUID optionId;
|
||||
|
||||
public static AnswerSelectedOptionResponse from(AnswerSelectedOption answerSelectedOption) {
|
||||
if (answerSelectedOption == null) {
|
||||
return null;
|
||||
}
|
||||
return AnswerSelectedOptionResponse.builder()
|
||||
.answerId(answerSelectedOption.getAnswerId())
|
||||
.optionId(answerSelectedOption.getOptionId())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
//답변 업데이트 요청 DTO (주로 단답/주관식/단일 선택용)
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AnswerUpdateRequest {
|
||||
private String answerText;
|
||||
private UUID selectedOptionId;
|
||||
// 다중 선택 옵션 업데이트는 AnswerSelectedOption 관련 별도 요청 사용 권장
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.Question;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
// 문항 생성 요청 DTO
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class QuestionCreateRequest {
|
||||
private UUID surveyId; // 어떤 설문에 속하는지
|
||||
private String questionText;
|
||||
private String questionType;
|
||||
private Integer questionOrder;
|
||||
private Boolean isRequired;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.QuestionOption;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
// 선택지 생성 요청 DTO
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class QuestionOptionCreateRequest {
|
||||
private UUID questionId; // 어떤 문항에 속하는지
|
||||
private String optionText;
|
||||
private Integer optionOrder;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.QuestionOption;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
// 선택지 응답 DTO
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class QuestionOptionResponse {
|
||||
private UUID optionId;
|
||||
private UUID questionId; // 어떤 문항에 속하는지
|
||||
private String optionText;
|
||||
private Integer optionOrder;
|
||||
|
||||
public static QuestionOptionResponse from(QuestionOption option) {
|
||||
if (option == null) {
|
||||
return null;
|
||||
}
|
||||
return QuestionOptionResponse.builder()
|
||||
.optionId(option.getOptionId())
|
||||
.questionId(option.getQuestionId())
|
||||
.optionText(option.getOptionText())
|
||||
.optionOrder(option.getOptionOrder())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.QuestionOption;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
// 선택지 업데이트 요청 DTO
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class QuestionOptionUpdateRequest {
|
||||
private String optionText;
|
||||
private Integer optionOrder;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import sgis.surveysystem.domain.Question;
|
||||
|
||||
//문항 응답 DTO (선택지 포함 가능)
|
||||
@Getter
|
||||
@Setter // Setter가 필요한 경우 (예: Controller에서 옵션 리스트를 동적으로 설정)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class QuestionResponse {
|
||||
private UUID questionId;
|
||||
private UUID surveyId; // 어떤 설문에 속하는지
|
||||
private String questionText;
|
||||
private String questionType;
|
||||
private Integer questionOrder;
|
||||
private Boolean isRequired;
|
||||
private List<QuestionOptionResponse> options; // 객관식 문항의 선택지 리스트 (서비스/컨트롤러에서 채움)
|
||||
|
||||
public static QuestionResponse from(Question question) {
|
||||
if (question == null) {
|
||||
return null;
|
||||
}
|
||||
return QuestionResponse.builder()
|
||||
.questionId(question.getQuestionId())
|
||||
.surveyId(question.getSurveyId())
|
||||
.questionText(question.getQuestionText())
|
||||
.questionType(question.getQuestionType())
|
||||
.questionOrder(question.getQuestionOrder())
|
||||
.isRequired(question.getIsRequired())
|
||||
// options 필드는 기본적으로 null로 두고, Controller/Service에서 필요한 경우 채웁니다.
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
//문항 업데이트 요청 DTO
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class QuestionUpdateRequest {
|
||||
private String questionText;
|
||||
private String questionType;
|
||||
private Integer questionOrder;
|
||||
private Boolean isRequired;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
|
||||
// 응답자 생성 요청 DTO (회원용/익명용)
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RespondentCreateRequest {
|
||||
private String userId; // 시스템 내 사용자 ID (회원인 경우)
|
||||
private String ipAddress; // 응답자의 IP 주소
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.Respondent;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
// 응답자 응답 DTO
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RespondentResponse {
|
||||
private UUID respondentId;
|
||||
private String userId;
|
||||
private String ipAddress;
|
||||
private LocalDateTime responseStartAt;
|
||||
private LocalDateTime responseEndAt;
|
||||
|
||||
public static RespondentResponse from(Respondent respondent) {
|
||||
if (respondent == null) {
|
||||
return null;
|
||||
}
|
||||
return RespondentResponse.builder()
|
||||
.respondentId(respondent.getRespondentId())
|
||||
.userId(respondent.getUserId())
|
||||
.ipAddress(respondent.getIpAddress())
|
||||
.responseStartAt(respondent.getResponseStartAt())
|
||||
.responseEndAt(respondent.getResponseEndAt())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.Respondent;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
// 응답자 업데이트 요청 DTO (주로 응답 완료 시간 업데이트 등에 사용)
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RespondentUpdateRequest {
|
||||
private String userId;
|
||||
private String ipAddress;
|
||||
private LocalDateTime responseEndAt;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.Survey; // 도메인 객체를 DTO로 변환하기 위해 필요
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor; // 모든 필드를 인자로 받는 생성자 추가 (선택 사항이지만 유용)
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
// 설문 생성 요청 DTO: 클라이언트에서 설문 생성 시 보내는 데이터
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor // 요청 DTO는 모든 필드 생성자도 유용
|
||||
public class SurveyCreateRequest {
|
||||
private String surveyTitle;
|
||||
private String surveyDescription;
|
||||
private LocalDateTime startDate;
|
||||
private LocalDateTime endDate;
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.Survey; // Import Survey domain object
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
// Survey 응답 DTO: 서버에서 클라이언트로 설문 정보를 보낼 때 사용하는 데이터
|
||||
@Getter
|
||||
@Setter // DTO가 데이터를 받을 때 Setter가 필요할 수 있음
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor // Lombok이 모든 필드를 인자로 받는 생성자를 생성
|
||||
@Builder // <--- 클래스 레벨에 @Builder 어노테이션
|
||||
public class SurveyResponse {
|
||||
private UUID surveyId;
|
||||
private String surveyTitle;
|
||||
private String surveyDescription;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private Boolean isActive;
|
||||
private LocalDateTime startDate;
|
||||
private LocalDateTime endDate;
|
||||
|
||||
// Entity (도메인 객체)를 DTO로 변환하는 정적 팩토리 메서드
|
||||
public static SurveyResponse from(Survey survey) {
|
||||
if (survey == null) {
|
||||
return null;
|
||||
}
|
||||
return SurveyResponse.builder() // <--- 이 부분이 이제 정상적으로 호출될 것임
|
||||
.surveyId(survey.getSurveyId())
|
||||
.surveyTitle(survey.getSurveyTitle())
|
||||
.surveyDescription(survey.getSurveyDescription())
|
||||
.createdAt(survey.getCreatedAt())
|
||||
.updatedAt(survey.getUpdatedAt())
|
||||
.isActive(survey.getIsActive())
|
||||
.startDate(survey.getStartDate())
|
||||
.endDate(survey.getEndDate())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.SurveyResponse;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
// 설문 응답 세션 생성 요청 DTO
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SurveyResponseCreateRequest {
|
||||
private UUID surveyId;
|
||||
private UUID respondentId; // 익명 설문인 경우 null
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import sgis.surveysystem.domain.SurveyResponse;
|
||||
|
||||
//설문 응답 세션 응답 DTO
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SurveyResponseResponse {
|
||||
private UUID responseId;
|
||||
private UUID surveyId;
|
||||
private UUID respondentId;
|
||||
private LocalDateTime submittedAt;
|
||||
|
||||
public static SurveyResponseResponse from(SurveyResponse surveyResponse) {
|
||||
if (surveyResponse == null) {
|
||||
return null;
|
||||
}
|
||||
return SurveyResponseResponse.builder()
|
||||
.responseId(surveyResponse.getResponseId())
|
||||
.surveyId(surveyResponse.getSurveyId())
|
||||
.respondentId(surveyResponse.getRespondentId())
|
||||
.submittedAt(surveyResponse.getSubmittedAt())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package sgis.surveysystem.dto;
|
||||
|
||||
import sgis.surveysystem.domain.Survey; // 도메인 객체를 DTO로 변환하기 위해 필요
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor; // 모든 필드를 인자로 받는 생성자 추가 (선택 사항이지만 유용)
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
|
||||
// 설문 업데이트 요청 DTO: 클라이언트에서 설문 업데이트 시 보내는 데이터
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor // 요청 DTO는 모든 필드 생성자도 유용
|
||||
public class SurveyUpdateRequest {
|
||||
private String surveyTitle;
|
||||
private String surveyDescription;
|
||||
private Boolean isActive;
|
||||
private LocalDateTime startDate;
|
||||
private LocalDateTime endDate;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package sgis.surveysystem.mapper;
|
||||
|
||||
import sgis.surveysystem.domain.Answer;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Mapper
|
||||
public interface AnswerMapper {
|
||||
void insertAnswer(Answer answer);
|
||||
Optional<Answer> findAnswerById(UUID answerId);
|
||||
List<Answer> findAnswersByResponseId(UUID responseId);
|
||||
List<Answer> findAnswersByQuestionId(UUID questionId);
|
||||
void updateAnswer(Answer answer);
|
||||
void deleteAnswer(UUID answerId);
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package sgis.surveysystem.mapper;
|
||||
|
||||
import sgis.surveysystem.domain.AnswerSelectedOption;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Mapper
|
||||
public interface AnswerSelectedOptionMapper {
|
||||
void insertAnswerSelectedOption(AnswerSelectedOption answerSelectedOption);
|
||||
void insertMultipleAnswerSelectedOptions(List<AnswerSelectedOption> options); // 다중 선택 옵션 일괄 삽입
|
||||
List<AnswerSelectedOption> findOptionsByAnswerId(UUID answerId);
|
||||
void deleteByAnswerId(UUID answerId); // 특정 답변에 연결된 모든 선택 옵션 삭제
|
||||
void deleteAnswerSelectedOption(@Param("answerId") UUID answerId, @Param("optionId") UUID optionId); // 특정 선택 옵션 삭제
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package sgis.surveysystem.mapper;
|
||||
|
||||
import sgis.surveysystem.domain.Question;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Mapper
|
||||
public interface QuestionMapper {
|
||||
void insertQuestion(Question question);
|
||||
List<Question> findQuestionsBySurveyId(UUID surveyId);
|
||||
Optional<Question> findQuestionById(UUID questionId);
|
||||
void updateQuestion(Question question);
|
||||
void deleteQuestion(UUID questionId);
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package sgis.surveysystem.mapper;
|
||||
|
||||
import sgis.surveysystem.domain.QuestionOption;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Mapper
|
||||
public interface QuestionOptionMapper {
|
||||
void insertQuestionOption(QuestionOption option);
|
||||
List<QuestionOption> findOptionsByQuestionId(UUID questionId);
|
||||
Optional<QuestionOption> findQuestionOptionById(UUID optionId);
|
||||
void updateQuestionOption(QuestionOption option);
|
||||
void deleteQuestionOption(UUID optionId);
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package sgis.surveysystem.mapper;
|
||||
|
||||
import sgis.surveysystem.domain.Respondent;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface RespondentMapper {
|
||||
void insertRespondent(Respondent respondent);
|
||||
Optional<Respondent> findRespondentById(UUID respondentId);
|
||||
Optional<Respondent> findRespondentByUserId(String userId); // user_id로 응답자 찾기
|
||||
void updateRespondent(Respondent respondent);
|
||||
void deleteRespondent(UUID respondentId);
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package sgis.surveysystem.mapper;
|
||||
|
||||
import sgis.surveysystem.domain.Survey;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Mapper
|
||||
public interface SurveyMapper {
|
||||
void insertSurvey(Survey survey);
|
||||
List<Survey> findAllSurveys();
|
||||
Optional<Survey> findSurveyById(UUID surveyId);
|
||||
void updateSurvey(Survey survey);
|
||||
void deleteSurvey(UUID surveyId);
|
||||
void updateSurveyStatus(@Param("surveyId") UUID surveyId, @Param("isActive") Boolean isActive);
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package sgis.surveysystem.mapper;
|
||||
|
||||
import sgis.surveysystem.domain.SurveyResponse;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Mapper
|
||||
public interface SurveyResponseMapper {
|
||||
void insertSurveyResponse(SurveyResponse surveyResponse);
|
||||
Optional<SurveyResponse> findSurveyResponseById(UUID responseId);
|
||||
List<SurveyResponse> findResponsesBySurveyId(UUID surveyId);
|
||||
List<SurveyResponse> findResponsesByRespondentId(UUID respondentId);
|
||||
void deleteSurveyResponse(UUID responseId);
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
package sgis.surveysystem.service;
|
||||
|
||||
import sgis.surveysystem.domain.AnswerSelectedOption;
|
||||
import sgis.surveysystem.mapper.AnswerSelectedOptionMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 다중 선택 객관식 답변의 선택된 옵션(AnswerSelectedOption) 관련 비즈니스 로직을 처리하는 서비스 클래스.
|
||||
* Answer 테이블이 아닌 별도의 테이블에 저장되는 다중 선택 옵션을 관리합니다.
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional
|
||||
public class AnswerSelectedOptionService {
|
||||
|
||||
private final AnswerSelectedOptionMapper answerSelectedOptionMapper;
|
||||
private final AnswerService answerService; // 외래 키 연결 및 답변 유형 확인을 위해 주입
|
||||
private final QuestionOptionService questionOptionService; // 선택지 유효성 검사를 위해 주입
|
||||
|
||||
/**
|
||||
* 다중 선택 객관식 답변에 단일 선택지를 추가합니다.
|
||||
*
|
||||
* @param answerId 답변 고유 ID (해당 답변은 '객관식_다중' 유형이어야 함)
|
||||
* @param optionId 추가할 선택지 ID
|
||||
* @return 생성된 AnswerSelectedOption 객체
|
||||
* @throws IllegalArgumentException 답변 유형이 '객관식_다중'이 아닐 경우
|
||||
* @throws NoSuchElementException 관련 엔티티를 찾을 수 없을 경우
|
||||
*/
|
||||
public AnswerSelectedOption addSelectedOption(UUID answerId, UUID optionId) {
|
||||
// 답변 존재 여부 확인 및 해당 답변이 '객관식_다중' 유형인지 검증
|
||||
// (AnswerService의 getAnswerById를 통해 QuestionService를 거쳐 questionType 확인 필요)
|
||||
answerService.getAnswerById(answerId); // Answer 존재 확인
|
||||
// TODO: 여기에서 answerId에 해당하는 Question의 questionType이 '객관식_다중'인지 확인하는 로직 추가 권장
|
||||
|
||||
questionOptionService.getQuestionOptionById(optionId); // 선택지 존재 여부 확인
|
||||
|
||||
AnswerSelectedOption selectedOption = AnswerSelectedOption.builder()
|
||||
.answerId(answerId)
|
||||
.optionId(optionId)
|
||||
.build();
|
||||
answerSelectedOptionMapper.insertAnswerSelectedOption(selectedOption); // Mapper를 통해 선택 옵션 삽입
|
||||
return selectedOption;
|
||||
}
|
||||
|
||||
/**
|
||||
* 다중 선택 객관식 답변에 여러 선택지를 일괄 추가합니다.
|
||||
*
|
||||
* @param answerId 답변 고유 ID
|
||||
* @param optionIds 추가할 선택지 ID 목록
|
||||
* @throws IllegalArgumentException 답변 유형이 '객관식_다중'이 아닐 경우
|
||||
* @throws NoSuchElementException 관련 엔티티를 찾을 수 없을 경우
|
||||
*/
|
||||
public void addMultipleSelectedOptions(UUID answerId, List<UUID> optionIds) {
|
||||
answerService.getAnswerById(answerId); // Answer 존재 확인
|
||||
// TODO: 여기에서 answerId에 해당하는 Question의 questionType이 '객관식_다중'인지 확인하는 로직 추가 권장
|
||||
|
||||
if (optionIds == null || optionIds.isEmpty()) {
|
||||
return; // 추가할 옵션이 없으면 아무것도 하지 않습니다.
|
||||
}
|
||||
|
||||
List<AnswerSelectedOption> optionsToInsert = new ArrayList<>();
|
||||
for (UUID optionId : optionIds) {
|
||||
questionOptionService.getQuestionOptionById(optionId); // 각 선택지 유효성 검사
|
||||
optionsToInsert.add(AnswerSelectedOption.builder()
|
||||
.answerId(answerId)
|
||||
.optionId(optionId)
|
||||
.build());
|
||||
}
|
||||
answerSelectedOptionMapper.insertMultipleAnswerSelectedOptions(optionsToInsert); // Mapper를 통해 선택 옵션 일괄 삽입
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 답변에 선택된 모든 옵션을 조회합니다.
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param answerId 답변 고유 ID
|
||||
* @return 선택된 AnswerSelectedOption 객체 리스트
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public List<AnswerSelectedOption> getSelectedOptionsByAnswerId(UUID answerId) {
|
||||
answerService.getAnswerById(answerId); // 답변 존재 여부 확인
|
||||
return answerSelectedOptionMapper.findOptionsByAnswerId(answerId); // Mapper를 통해 선택된 옵션 목록 조회
|
||||
}
|
||||
|
||||
/**
|
||||
* 다중 선택 객관식 답변에서 특정 선택지를 제거합니다.
|
||||
*
|
||||
* @param answerId 답변 고유 ID
|
||||
* @param optionId 제거할 선택지 ID
|
||||
*/
|
||||
public void removeSelectedOption(UUID answerId, UUID optionId) {
|
||||
// 삭제 전에 해당 연결이 존재하는지 확인하는 로직을 추가할 수 있습니다.
|
||||
answerSelectedOptionMapper.deleteAnswerSelectedOption(answerId, optionId); // Mapper를 통해 특정 선택 옵션 삭제
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 답변에 연결된 모든 선택지를 제거합니다.
|
||||
*
|
||||
* @param answerId 답변 고유 ID
|
||||
*/
|
||||
public void removeAllSelectedOptionsByAnswerId(UUID answerId) {
|
||||
answerService.getAnswerById(answerId); // 답변 존재 여부 확인
|
||||
answerSelectedOptionMapper.deleteByAnswerId(answerId); // Mapper를 통해 답변에 연결된 모든 선택 옵션 삭제
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
package sgis.surveysystem.service;
|
||||
|
||||
import sgis.surveysystem.domain.Answer;
|
||||
import sgis.surveysystem.domain.AnswerSelectedOption;
|
||||
import sgis.surveysystem.mapper.AnswerMapper;
|
||||
import sgis.surveysystem.mapper.AnswerSelectedOptionMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 개별 문항 응답(Answer) 관련 비즈니스 로직을 처리하는 서비스 클래스.
|
||||
* 단답형, 주관식, 객관식 단일/다중 선택 응답을 관리합니다.
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional
|
||||
public class AnswerService {
|
||||
|
||||
private final AnswerMapper answerMapper;
|
||||
private final SurveyResponseService surveyResponseService; // 외래 키 연결을 위해 주입
|
||||
private final QuestionService questionService; // 외래 키 연결 및 문항 유형 확인을 위해 주입
|
||||
private final QuestionOptionService questionOptionService; // 선택지 유효성 검사 및 다중 선택 옵션 처리를 위해 주입
|
||||
private final AnswerSelectedOptionMapper answerSelectedOptionMapper; // 다중 선택 옵션 매퍼 주입
|
||||
|
||||
/**
|
||||
* 새로운 문항 응답을 생성합니다.
|
||||
* 문항 유형에 따라 answerText 또는 selectedOptionId(s)를 저장합니다.
|
||||
*
|
||||
* @param responseId 응답 세션 ID
|
||||
* @param questionId 문항 ID
|
||||
* @param answerText 단답형/주관식 응답 내용 (객관식은 null)
|
||||
* @param selectedOptionId 객관식 단일 선택 시 선택된 옵션 ID (다중 선택/단답/주관식은 null)
|
||||
* @param selectedOptionIds 객관식 다중 선택 시 선택된 옵션 ID 목록 (다른 유형은 null)
|
||||
* @return 생성된 Answer 객체
|
||||
* @throws IllegalArgumentException 유효하지 않은 응답 유형 또는 데이터가 제공될 경우
|
||||
* @throws NoSuchElementException 관련 엔티티(응답 세션, 문항, 선택지)를 찾을 수 없을 경우
|
||||
*/
|
||||
public Answer createAnswer(UUID responseId, UUID questionId, String answerText, UUID selectedOptionId, List<UUID> selectedOptionIds) {
|
||||
surveyResponseService.getSurveyResponseById(responseId); // 응답 세션 존재 여부 확인
|
||||
// 문항 존재 여부 확인 및 문항 유형 가져오기
|
||||
String questionType = questionService.getQuestionById(questionId).getQuestionType();
|
||||
|
||||
Answer answer = Answer.builder()
|
||||
.answerId(UUID.randomUUID()) // 애플리케이션에서 새로운 UUID 생성
|
||||
.responseId(responseId)
|
||||
.questionId(questionId)
|
||||
.build();
|
||||
|
||||
// 문항 유형에 따라 응답 데이터 유효성 검사 및 설정
|
||||
switch (questionType) {
|
||||
case "단답형":
|
||||
case "주관식":
|
||||
if (answerText == null || answerText.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("Short answer or essay questions require text answer.");
|
||||
}
|
||||
answer.setAnswerText(answerText);
|
||||
break;
|
||||
case "객관식_단일":
|
||||
if (selectedOptionId == null) {
|
||||
throw new IllegalArgumentException("Single choice question requires one selected option.");
|
||||
}
|
||||
questionOptionService.getQuestionOptionById(selectedOptionId); // 선택지 존재 여부 확인
|
||||
answer.setSelectedOptionId(selectedOptionId);
|
||||
break;
|
||||
case "객관식_다중":
|
||||
if (selectedOptionIds == null || selectedOptionIds.isEmpty()) {
|
||||
throw new IllegalArgumentException("Multiple choice question requires at least one selected option.");
|
||||
}
|
||||
// Answer 테이블에는 다중 선택 옵션이 직접 저장되지 않으므로, answerText와 selectedOptionId는 null로 유지
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid question type: " + questionType);
|
||||
}
|
||||
|
||||
answerMapper.insertAnswer(answer); // Answer 테이블에 기본 응답 정보 삽입
|
||||
|
||||
// 다중 선택 옵션이 있는 경우 AnswerSelectedOption 테이블에 추가 정보 삽입
|
||||
if ("객관식_다중".equals(questionType) && selectedOptionIds != null && !selectedOptionIds.isEmpty()) {
|
||||
List<AnswerSelectedOption> multiOptions = selectedOptionIds.stream()
|
||||
.map(optionId -> {
|
||||
questionOptionService.getQuestionOptionById(optionId); // 각 선택지 존재 여부 확인
|
||||
return AnswerSelectedOption.builder()
|
||||
.answerId(answer.getAnswerId())
|
||||
.optionId(optionId)
|
||||
.build();
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
answerSelectedOptionMapper.insertMultipleAnswerSelectedOptions(multiOptions); // 일괄 삽입
|
||||
}
|
||||
|
||||
return getAnswerById(answer.getAnswerId()); // 최종적으로 저장된 Answer 객체 반환
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 답변을 조회합니다. (객관식 다중 선택 옵션이 있다면 함께 로드)
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param answerId 답변 고유 ID
|
||||
* @return 조회된 Answer 객체
|
||||
* @throws NoSuchElementException 해당 ID의 답변이 없을 경우
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Answer getAnswerById(UUID answerId) {
|
||||
Answer answer = answerMapper.findAnswerById(answerId)
|
||||
.orElseThrow(() -> new NoSuchElementException("Answer not found with ID: " + answerId));
|
||||
|
||||
// 문항 유형이 '객관식_다중'인 경우, AnswerSelectedOption에서 추가 선택지를 로드하여 Answer 객체에 설정합니다.
|
||||
// (Answer 도메인 객체에 List<AnswerSelectedOption> options 필드를 추가하고 Setter를 통해 설정 가능)
|
||||
String questionType = questionService.getQuestionById(answer.getQuestionId()).getQuestionType();
|
||||
if ("객관식_다중".equals(questionType)) {
|
||||
List<AnswerSelectedOption> selectedOptions = answerSelectedOptionMapper.findOptionsByAnswerId(answerId);
|
||||
// 예시: answer.setAnswerSelectedOptions(selectedOptions); // Answer 도메인에 필드 추가 필요
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 응답 세션에 대한 모든 답변을 조회합니다. (각 답변의 다중 선택 옵션도 함께 로드)
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param responseId 응답 세션 고유 ID
|
||||
* @return 해당 응답 세션의 모든 Answer 객체 리스트
|
||||
* @throws NoSuchElementException 해당 응답 세션 ID가 없을 경우
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public List<Answer> getAnswersByResponseId(UUID responseId) {
|
||||
surveyResponseService.getSurveyResponseById(responseId); // 응답 세션 존재 여부 확인
|
||||
List<Answer> answers = answerMapper.findAnswersByResponseId(responseId);
|
||||
|
||||
// 각 답변에 대해 다중 선택 옵션을 로드합니다.
|
||||
for (Answer answer : answers) {
|
||||
String questionType = questionService.getQuestionById(answer.getQuestionId()).getQuestionType();
|
||||
if ("객관식_다중".equals(questionType)) {
|
||||
List<AnswerSelectedOption> selectedOptions = answerSelectedOptionMapper.findOptionsByAnswerId(answer.getAnswerId());
|
||||
// 예시: answer.setAnswerSelectedOptions(selectedOptions); // Answer 도메인에 필드 추가 필요
|
||||
}
|
||||
}
|
||||
return answers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 답변을 업데이트합니다. (단답형, 주관식, 객관식 단일 선택만 해당)
|
||||
* 객관식 다중 선택 문항의 옵션 업데이트는 AnswerSelectedOptionService를 통해 별도로 처리해야 합니다.
|
||||
*
|
||||
* @param answerId 업데이트할 답변 고유 ID
|
||||
* @param answerText 새로운 단답형/주관식 내용
|
||||
* @param selectedOptionId 새로운 객관식 단일 선택 옵션 ID
|
||||
* @return 업데이트된 Answer 객체
|
||||
* @throws IllegalArgumentException 유효하지 않은 응답 데이터 또는 다중 선택 문항에 대한 시도
|
||||
* @throws NoSuchElementException 해당 ID의 답변이 없을 경우
|
||||
*/
|
||||
public Answer updateAnswer(UUID answerId, String answerText, UUID selectedOptionId) {
|
||||
Answer existingAnswer = getAnswerById(answerId); // 기존 답변 조회
|
||||
String questionType = questionService.getQuestionById(existingAnswer.getQuestionId()).getQuestionType();
|
||||
|
||||
// 다중 선택 문항은 이 메서드로 업데이트하지 않도록 제약
|
||||
if ("객관식_다중".equals(questionType)) {
|
||||
throw new IllegalArgumentException("Multi-select answers should be updated via specific methods (e.g., in AnswerSelectedOptionService).");
|
||||
}
|
||||
|
||||
Answer answer = Answer.builder()
|
||||
.answerId(answerId)
|
||||
.responseId(existingAnswer.getResponseId()) // 기존 응답 세션 ID 유지
|
||||
.questionId(existingAnswer.getQuestionId()) // 기존 문항 ID 유지
|
||||
.answerText(answerText)
|
||||
.selectedOptionId(selectedOptionId)
|
||||
.build();
|
||||
|
||||
answerMapper.updateAnswer(answer); // Mapper를 통해 답변 정보 업데이트
|
||||
return getAnswerById(answerId); // 업데이트된 최신 정보 반환
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 답변을 삭제합니다.
|
||||
* 객관식 다중 선택 문항의 경우, 관련 AnswerSelectedOption 레코드도 함께 삭제됩니다.
|
||||
*
|
||||
* @param answerId 삭제할 답변 고유 ID
|
||||
* @throws NoSuchElementException 해당 ID의 답변이 없을 경우
|
||||
*/
|
||||
public void deleteAnswer(UUID answerId) {
|
||||
getAnswerById(answerId); // 삭제할 답변이 존재하는지 먼저 확인합니다.
|
||||
|
||||
// 다중 선택 옵션이 있다면 먼저 삭제하여 외래 키 제약조건 위배를 방지합니다.
|
||||
answerSelectedOptionMapper.deleteByAnswerId(answerId);
|
||||
|
||||
answerMapper.deleteAnswer(answerId); // Mapper를 통해 답변 삭제
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package sgis.surveysystem.service;
|
||||
|
||||
import sgis.surveysystem.domain.QuestionOption;
|
||||
import sgis.surveysystem.mapper.QuestionOptionMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 객관식 문항 선택지(QuestionOption) 관련 비즈니스 로직을 처리하는 서비스 클래스.
|
||||
* MyBatis Mapper를 통해 데이터베이스와 상호작용합니다.
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional
|
||||
public class QuestionOptionService {
|
||||
|
||||
private final QuestionOptionMapper questionOptionMapper;
|
||||
private final QuestionService questionService; // 선택지가 속할 문항의 유효성 검사를 위해 QuestionService 주입
|
||||
|
||||
/**
|
||||
* 새로운 객관식 문항 선택지를 생성합니다.
|
||||
* 선택지 ID는 애플리케이션에서 UUID를 생성하여 할당합니다.
|
||||
*
|
||||
* @param questionId 선택지가 속할 문항 ID
|
||||
* @param optionText 선택지 내용
|
||||
* @param optionOrder 문항 내 선택지 순서
|
||||
* @return 생성된 QuestionOption 객체
|
||||
* @throws NoSuchElementException 해당 문항 ID가 유효하지 않을 경우
|
||||
*/
|
||||
public QuestionOption createQuestionOption(UUID questionId, String optionText, Integer optionOrder) {
|
||||
// 선택지가 속할 문항이 존재하는지 먼저 확인합니다.
|
||||
questionService.getQuestionById(questionId);
|
||||
// TODO: 해당 Question의 questionType이 '객관식_단일' 또는 '객관식_다중'인지 검증하는 로직 추가를 권장합니다.
|
||||
|
||||
QuestionOption option = QuestionOption.builder()
|
||||
.optionId(UUID.randomUUID()) // 애플리케이션에서 새로운 UUID 생성
|
||||
.questionId(questionId)
|
||||
.optionText(optionText)
|
||||
.optionOrder(optionOrder)
|
||||
.build();
|
||||
questionOptionMapper.insertQuestionOption(option); // Mapper를 통해 데이터베이스에 선택지 정보 삽입
|
||||
return option;
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 문항에 속한 모든 선택지를 순서대로 조회합니다.
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param questionId 문항 고유 ID
|
||||
* @return 해당 문항의 모든 QuestionOption 객체 리스트
|
||||
* @throws NoSuchElementException 해당 문항 ID가 유효하지 않을 경우
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public List<QuestionOption> getOptionsByQuestionId(UUID questionId) {
|
||||
questionService.getQuestionById(questionId); // 문항 존재 여부 확인
|
||||
return questionOptionMapper.findOptionsByQuestionId(questionId); // Mapper를 통해 문항 ID로 선택지 목록 조회
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 선택지를 조회합니다.
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param optionId 선택지 고유 ID
|
||||
* @return 조회된 QuestionOption 객체
|
||||
* @throws NoSuchElementException 해당 ID의 선택지가 데이터베이스에 없을 경우 발생
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public QuestionOption getQuestionOptionById(UUID optionId) {
|
||||
return questionOptionMapper.findQuestionOptionById(optionId) // Mapper를 통해 ID로 선택지 조회
|
||||
.orElseThrow(() -> new NoSuchElementException("Question Option not found with ID: " + optionId)); // 없을 경우 예외 발생
|
||||
}
|
||||
|
||||
/**
|
||||
* 선택지 정보를 업데이트합니다.
|
||||
* 업데이트 전에 해당 선택지가 존재하는지 확인합니다.
|
||||
*
|
||||
* @param optionId 업데이트할 선택지의 고유 ID
|
||||
* @param optionText 새로운 선택지 내용
|
||||
* @param optionOrder 새로운 선택지 순서
|
||||
* @return 업데이트된 QuestionOption 객체 (업데이트 후 다시 조회하여 최신 상태 반환)
|
||||
* @throws NoSuchElementException 해당 ID의 선택지가 없을 경우
|
||||
*/
|
||||
public QuestionOption updateQuestionOption(UUID optionId, String optionText, Integer optionOrder) {
|
||||
getQuestionOptionById(optionId); // 업데이트할 선택지가 존재하는지 먼저 확인합니다.
|
||||
|
||||
QuestionOption option = QuestionOption.builder()
|
||||
.optionId(optionId) // 업데이트 대상 선택지 ID
|
||||
.optionText(optionText)
|
||||
.optionOrder(optionOrder)
|
||||
.build();
|
||||
questionOptionMapper.updateQuestionOption(option); // Mapper를 통해 선택지 정보 업데이트
|
||||
|
||||
return getQuestionOptionById(optionId); // 업데이트된 최신 정보를 다시 조회하여 반환합니다.
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 선택지를 삭제합니다.
|
||||
* 삭제 전에 해당 선택지가 존재하는지 확인합니다.
|
||||
*
|
||||
* @param optionId 삭제할 선택지의 고유 ID
|
||||
* @throws NoSuchElementException 해당 ID의 선택지가 없을 경우
|
||||
*/
|
||||
public void deleteQuestionOption(UUID optionId) {
|
||||
getQuestionOptionById(optionId); // 삭제할 선택지가 존재하는지 먼저 확인합니다.
|
||||
questionOptionMapper.deleteQuestionOption(optionId); // Mapper를 통해 선택지 삭제
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package sgis.surveysystem.service;
|
||||
|
||||
import sgis.surveysystem.domain.Question;
|
||||
import sgis.surveysystem.mapper.QuestionMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 설문 문항(Question) 관련 비즈니스 로직을 처리하는 서비스 클래스.
|
||||
* MyBatis Mapper를 통해 데이터베이스와 상호작용합니다.
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional
|
||||
public class QuestionService {
|
||||
|
||||
private final QuestionMapper questionMapper;
|
||||
private final SurveyService surveyService; // 문항이 속할 설문의 유효성 검사를 위해 SurveyService 주입
|
||||
|
||||
/**
|
||||
* 새로운 설문 문항을 생성합니다.
|
||||
* 문항 ID는 애플리케이션에서 UUID를 생성하여 할당합니다.
|
||||
*
|
||||
* @param surveyId 문항이 속할 설문 ID
|
||||
* @param questionText 문항 내용
|
||||
* @param questionType 문항 유형 ('단답형', '객관식_단일', '객관식_다중', '주관식')
|
||||
* @param questionOrder 설문 내 문항 순서
|
||||
* @param isRequired 필수 응답 여부
|
||||
* @return 생성된 Question 객체
|
||||
* @throws NoSuchElementException 해당 설문 ID가 유효하지 않을 경우
|
||||
*/
|
||||
public Question createQuestion(UUID surveyId, String questionText, String questionType, Integer questionOrder, Boolean isRequired) {
|
||||
// 문항이 속할 설문이 존재하는지 먼저 확인하여 외래 키 제약조건 위배를 방지합니다.
|
||||
surveyService.getSurveyById(surveyId);
|
||||
|
||||
Question question = Question.builder()
|
||||
.questionId(UUID.randomUUID()) // 애플리케이션에서 새로운 UUID 생성
|
||||
.surveyId(surveyId)
|
||||
.questionText(questionText)
|
||||
.questionType(questionType)
|
||||
.questionOrder(questionOrder)
|
||||
.isRequired(isRequired)
|
||||
.build();
|
||||
questionMapper.insertQuestion(question); // Mapper를 통해 데이터베이스에 문항 정보 삽입
|
||||
return question;
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 설문에 속한 모든 문항을 순서대로 조회합니다.
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param surveyId 설문 고유 ID
|
||||
* @return 해당 설문의 모든 Question 객체 리스트
|
||||
* @throws NoSuchElementException 해당 설문 ID가 유효하지 않을 경우
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public List<Question> getQuestionsBySurveyId(UUID surveyId) {
|
||||
surveyService.getSurveyById(surveyId); // 설문 존재 여부 확인
|
||||
return questionMapper.findQuestionsBySurveyId(surveyId); // Mapper를 통해 설문 ID로 문항 목록 조회
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 문항을 조회합니다.
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param questionId 문항 고유 ID
|
||||
* @return 조회된 Question 객체
|
||||
* @throws NoSuchElementException 해당 ID의 문항이 데이터베이스에 없을 경우 발생
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Question getQuestionById(UUID questionId) {
|
||||
return questionMapper.findQuestionById(questionId) // Mapper를 통해 ID로 문항 조회
|
||||
.orElseThrow(() -> new NoSuchElementException("Question not found with ID: " + questionId)); // 없을 경우 예외 발생
|
||||
}
|
||||
|
||||
/**
|
||||
* 문항 정보를 업데이트합니다.
|
||||
* 업데이트 전에 해당 문항이 존재하는지 확인합니다.
|
||||
*
|
||||
* @param questionId 업데이트할 문항의 고유 ID
|
||||
* @param questionText 새로운 문항 내용
|
||||
* @param questionType 새로운 문항 유형
|
||||
* @param questionOrder 새로운 문항 순서
|
||||
* @param isRequired 새로운 필수 응답 여부
|
||||
* @return 업데이트된 Question 객체 (업데이트 후 다시 조회하여 최신 상태 반환)
|
||||
* @throws NoSuchElementException 해당 ID의 문항이 없을 경우
|
||||
*/
|
||||
public Question updateQuestion(UUID questionId, String questionText, String questionType, Integer questionOrder, Boolean isRequired) {
|
||||
getQuestionById(questionId); // 업데이트할 문항이 존재하는지 먼저 확인합니다.
|
||||
|
||||
Question question = Question.builder()
|
||||
.questionId(questionId) // 업데이트 대상 문항 ID
|
||||
.questionText(questionText)
|
||||
.questionType(questionType)
|
||||
.questionOrder(questionOrder)
|
||||
.isRequired(isRequired)
|
||||
.build();
|
||||
questionMapper.updateQuestion(question); // Mapper를 통해 문항 정보 업데이트
|
||||
|
||||
return getQuestionById(questionId); // 업데이트된 최신 정보를 다시 조회하여 반환합니다.
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 문항을 삭제합니다.
|
||||
* 삭제 전에 해당 문항이 존재하는지 확인합니다.
|
||||
*
|
||||
* @param questionId 삭제할 문항의 고유 ID
|
||||
* @throws NoSuchElementException 해당 ID의 문항이 없을 경우
|
||||
*/
|
||||
public void deleteQuestion(UUID questionId) {
|
||||
getQuestionById(questionId); // 삭제할 문항이 존재하는지 먼저 확인합니다.
|
||||
questionMapper.deleteQuestion(questionId); // Mapper를 통해 문항 삭제
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
package sgis.surveysystem.service;
|
||||
|
||||
import sgis.surveysystem.domain.Respondent;
|
||||
import sgis.surveysystem.mapper.RespondentMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 응답자(Respondent) 관련 비즈니스 로직을 처리하는 서비스 클래스.
|
||||
* MyBatis Mapper를 통해 데이터베이스와 상호작용합니다.
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional
|
||||
public class RespondentService {
|
||||
|
||||
private final RespondentMapper respondentMapper;
|
||||
|
||||
/**
|
||||
* 새로운 응답자를 생성하거나, user_id가 주어지고 해당 user_id로 이미 존재하는 응답자를 조회합니다.
|
||||
*
|
||||
* @param userId 시스템 내 사용자 ID (선택 사항, 익명 응답 시 null)
|
||||
* @param ipAddress 응답자의 IP 주소 (선택 사항)
|
||||
* @return 생성되거나 조회된 Respondent 객체
|
||||
*/
|
||||
public Respondent createOrGetRespondent(String userId, String ipAddress) {
|
||||
// user_id가 제공된 경우, 기존 응답자가 있는지 먼저 확인합니다.
|
||||
if (userId != null && !userId.isEmpty()) {
|
||||
Optional<Respondent> existingRespondent = respondentMapper.findRespondentByUserId(userId);
|
||||
if (existingRespondent.isPresent()) {
|
||||
return existingRespondent.get(); // 이미 존재하는 응답자 반환
|
||||
}
|
||||
}
|
||||
|
||||
// 기존 응답자가 없거나 user_id가 제공되지 않은 경우, 새로운 응답자를 생성합니다.
|
||||
Respondent respondent = Respondent.builder()
|
||||
.respondentId(UUID.randomUUID()) // 애플리케이션에서 새로운 UUID 생성
|
||||
.userId(userId)
|
||||
.ipAddress(ipAddress)
|
||||
.responseStartAt(LocalDateTime.now()) // 응답 시작 시점 기록
|
||||
.build();
|
||||
respondentMapper.insertRespondent(respondent); // Mapper를 통해 응답자 정보 삽입
|
||||
return respondent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 응답자를 조회합니다.
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param respondentId 응답자 고유 ID
|
||||
* @return 조회된 Respondent 객체
|
||||
* @throws NoSuchElementException 해당 ID의 응답자가 데이터베이스에 없을 경우 발생
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Respondent getRespondentById(UUID respondentId) {
|
||||
return respondentMapper.findRespondentById(respondentId) // Mapper를 통해 ID로 응답자 조회
|
||||
.orElseThrow(() -> new NoSuchElementException("Respondent not found with ID: " + respondentId)); // 없을 경우 예외 발생
|
||||
}
|
||||
|
||||
/**
|
||||
* 응답자 정보를 업데이트합니다.
|
||||
* 업데이트 전에 해당 응답자가 존재하는지 확인합니다.
|
||||
*
|
||||
* @param respondentId 업데이트할 응답자 고유 ID
|
||||
* @param userId 새로운 사용자 ID
|
||||
* @param ipAddress 새로운 IP 주소
|
||||
* @param responseEndAt 응답 완료 일시 (null이면 현재 시각으로 설정)
|
||||
* @return 업데이트된 Respondent 객체 (업데이트 후 다시 조회하여 최신 상태 반환)
|
||||
* @throws NoSuchElementException 해당 ID의 응답자가 없을 경우
|
||||
*/
|
||||
public Respondent updateRespondent(UUID respondentId, String userId, String ipAddress, LocalDateTime responseEndAt) {
|
||||
getRespondentById(respondentId); // 업데이트할 응답자가 존재하는지 먼저 확인합니다.
|
||||
|
||||
Respondent respondent = Respondent.builder()
|
||||
.respondentId(respondentId) // 업데이트 대상 응답자 ID
|
||||
.userId(userId)
|
||||
.ipAddress(ipAddress)
|
||||
.responseEndAt(responseEndAt != null ? responseEndAt : LocalDateTime.now()) // 완료 시점 갱신 또는 현재 시각
|
||||
.build();
|
||||
respondentMapper.updateRespondent(respondent); // Mapper를 통해 응답자 정보 업데이트
|
||||
return getRespondentById(respondentId); // 업데이트된 최신 정보를 다시 조회하여 반환합니다.
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 응답자를 삭제합니다.
|
||||
* 삭제 전에 해당 응답자가 존재하는지 확인합니다.
|
||||
*
|
||||
* @param respondentId 삭제할 응답자 고유 ID
|
||||
* @throws NoSuchElementException 해당 ID의 응답자가 없을 경우
|
||||
*/
|
||||
public void deleteRespondent(UUID respondentId) {
|
||||
getRespondentById(respondentId); // 삭제할 응답자가 존재하는지 먼저 확인합니다.
|
||||
respondentMapper.deleteRespondent(respondentId); // Mapper를 통해 응답자 삭제
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package sgis.surveysystem.service;
|
||||
|
||||
import sgis.surveysystem.domain.SurveyResponse;
|
||||
import sgis.surveysystem.mapper.SurveyResponseMapper;
|
||||
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.UUID;
|
||||
|
||||
/**
|
||||
* 설문 응답 세션(SurveyResponse) 관련 비즈니스 로직을 처리하는 서비스 클래스.
|
||||
* 사용자가 설문을 제출할 때마다 생성되는 응답 세션을 관리합니다.
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional
|
||||
public class SurveyResponseService {
|
||||
|
||||
private final SurveyResponseMapper surveyResponseMapper;
|
||||
private final SurveyService surveyService; // 외래 키 연결을 위해 SurveyService 주입
|
||||
private final RespondentService respondentService; // 외래 키 연결을 위해 RespondentService 주입
|
||||
|
||||
/**
|
||||
* 새로운 설문 응답 세션을 생성합니다.
|
||||
* 응답 세션 ID는 애플리케이션에서 UUID를 생성하여 할당합니다.
|
||||
*
|
||||
* @param surveyId 응답이 속한 설문 ID
|
||||
* @param respondentId 응답자 ID (선택 사항, 익명 설문인 경우 null)
|
||||
* @return 생성된 SurveyResponse 객체
|
||||
* @throws NoSuchElementException 설문 ID 또는 응답자 ID가 유효하지 않을 경우
|
||||
*/
|
||||
public SurveyResponse createSurveyResponse(UUID surveyId, UUID respondentId) {
|
||||
surveyService.getSurveyById(surveyId); // 설문 존재 여부 확인
|
||||
|
||||
// 응답자 ID가 제공된 경우, 해당 응답자가 존재하는지 확인합니다.
|
||||
if (respondentId != null) {
|
||||
respondentService.getRespondentById(respondentId);
|
||||
}
|
||||
|
||||
SurveyResponse surveyResponse = SurveyResponse.builder()
|
||||
.responseId(UUID.randomUUID()) // 애플리케이션에서 새로운 UUID 생성
|
||||
.surveyId(surveyId)
|
||||
.respondentId(respondentId)
|
||||
.submittedAt(LocalDateTime.now()) // 제출 시점 기록
|
||||
.build();
|
||||
surveyResponseMapper.insertSurveyResponse(surveyResponse); // Mapper를 통해 응답 세션 정보 삽입
|
||||
return surveyResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 설문 응답 세션을 조회합니다.
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param responseId 응답 세션 고유 ID
|
||||
* @return 조회된 SurveyResponse 객체
|
||||
* @throws NoSuchElementException 해당 ID의 응답 세션이 데이터베이스에 없을 경우 발생
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public SurveyResponse getSurveyResponseById(UUID responseId) {
|
||||
return surveyResponseMapper.findSurveyResponseById(responseId) // Mapper를 통해 ID로 응답 세션 조회
|
||||
.orElseThrow(() -> new NoSuchElementException("Survey Response not found with ID: " + responseId)); // 없을 경우 예외 발생
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 설문에 대한 모든 응답 세션을 조회합니다.
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param surveyId 설문 고유 ID
|
||||
* @return 해당 설문의 모든 SurveyResponse 객체 리스트
|
||||
* @throws NoSuchElementException 해당 설문 ID가 유효하지 않을 경우
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public List<SurveyResponse> getSurveyResponsesBySurveyId(UUID surveyId) {
|
||||
surveyService.getSurveyById(surveyId); // 설문 존재 여부 확인
|
||||
return surveyResponseMapper.findResponsesBySurveyId(surveyId); // Mapper를 통해 설문 ID로 응답 세션 목록 조회
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 응답자가 제출한 모든 응답 세션을 조회합니다.
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param respondentId 응답자 고유 ID
|
||||
* @return 해당 응답자의 모든 SurveyResponse 객체 리스트
|
||||
* @throws NoSuchElementException 해당 응답자 ID가 유효하지 않을 경우
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public List<SurveyResponse> getSurveyResponsesByRespondentId(UUID respondentId) {
|
||||
respondentService.getRespondentById(respondentId); // 응답자 존재 여부 확인
|
||||
return surveyResponseMapper.findResponsesByRespondentId(respondentId); // Mapper를 통해 응답자 ID로 응답 세션 목록 조회
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 설문 응답 세션을 삭제합니다.
|
||||
* 삭제 전에 해당 응답 세션이 존재하는지 확인합니다.
|
||||
*
|
||||
* @param responseId 삭제할 응답 세션 고유 ID
|
||||
* @throws NoSuchElementException 해당 ID의 응답 세션이 없을 경우
|
||||
*/
|
||||
public void deleteSurveyResponse(UUID responseId) {
|
||||
getSurveyResponseById(responseId); // 삭제할 응답 세션이 존재하는지 먼저 확인합니다.
|
||||
surveyResponseMapper.deleteSurveyResponse(responseId); // Mapper를 통해 응답 세션 삭제
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
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.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<Survey> getAllSurveys() {
|
||||
return surveyMapper.findAllSurveys(); // Mapper를 통해 모든 설문 조회
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 ID의 설문을 조회합니다.
|
||||
* 읽기 전용 트랜잭션으로 설정합니다.
|
||||
*
|
||||
* @param surveyId 설문 고유 ID
|
||||
* @return 조회된 Survey 객체
|
||||
* @throws NoSuchElementException 해당 ID의 설문이 데이터베이스에 없을 경우 발생
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Survey getSurveyById(UUID surveyId) {
|
||||
return surveyMapper.findSurveyById(surveyId) // Mapper를 통해 ID로 설문 조회
|
||||
.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); // 업데이트된 상태로 반환
|
||||
}
|
||||
}
|
||||
|
|
@ -514,4 +514,54 @@ FROM (SELECT ROWNUM RNK,
|
|||
</foreach>
|
||||
|
||||
</select>
|
||||
|
||||
<select id="mapBoreholeLogHeader" parameterType="map" resultType="egovMap">
|
||||
SELECT
|
||||
ap.project_code,
|
||||
hole.hole_code AS HOLE_CODE,
|
||||
ap.project_name,
|
||||
cc1.code_txt ||
|
||||
CASE
|
||||
WHEN cc2.code_txt IS NOT NULL THEN ' ' || cc2.code_txt
|
||||
ELSE ''
|
||||
END AS COMPANY,
|
||||
hole.hole_name AS HOLE_NAME,
|
||||
cc3.code_txt AS DISTRICT,
|
||||
hole.hole_x AS HOLE_OR_X,
|
||||
hole.hole_y AS HOLE_OR_Y,
|
||||
hole.HOLE_ELEVATION AS HOLE_EL,
|
||||
hole.HOLE_END_DATE AS HOLE_DATE_TO,
|
||||
hole.HOLE_DRILLING_DEPTH AS HOLE_TOTAL_DEPTH,
|
||||
hole.HOLE_CASING_DEPTH AS HOLE_CASING_DEPTH,
|
||||
hole.HOLE_WATER_LEVEL AS hole_wl,
|
||||
hole.HOLE_BORING_MACHINE AS HOLE_BORING_MACHINE,
|
||||
hole.HOLE_BORING_METHOD AS HOLE_BORING_METHOD,
|
||||
hole.HOLE_BORING_NAME AS HOLE_BORING_BY,
|
||||
'N/A' AS HOLE_INSPECTED_BY,
|
||||
REPLACE((epsg_code.code_txt || ' ' || epsg_code2.code_txt), '(BESSEL)','') AS COORDINATE_L,
|
||||
(
|
||||
SELECT
|
||||
CASE
|
||||
WHEN MAX(layer.LAYER_DEPTH_TO::NUMERIC) >= 34.6 THEN 3
|
||||
WHEN MAX(layer.LAYER_DEPTH_TO::NUMERIC) >= 17.3 THEN 2
|
||||
ELSE 1
|
||||
END
|
||||
FROM APPTB_LAYR01 layer
|
||||
WHERE layer.business_code = hole.business_code -- 현재 행의 business_code 사용
|
||||
AND layer.hole_code = hole.hole_code -- 현재 행의 hole_code 사용
|
||||
) AS PAGE_NUM
|
||||
FROM APPTB_HOLE01 hole
|
||||
LEFT JOIN APPTB_SAUP01 business ON hole.business_code = business.business_code
|
||||
LEFT JOIN APPTB_PROJ01 ap ON business.project_code = ap.project_code
|
||||
LEFT JOIN comtb_code02 cc1 ON ap.project_ordering_code = cc1.code_val
|
||||
LEFT JOIN comtb_code02 cc2 ON ap.project_affiliated_code = cc2.code_val
|
||||
LEFT JOIN comtb_code02 cc3 ON ap.project_harbor_code = cc3.code_val
|
||||
LEFT JOIN comtb_code02 epsg_code ON ap.PROJECT_EPSG_CODE = epsg_code.code_val
|
||||
LEFT JOIN comtb_code02 epsg_code2 ON hole.hole_coordinate = epsg_code2.code_val
|
||||
WHERE
|
||||
hole.business_code = #{businessCode} AND
|
||||
hole.hole_code = #{holeCode}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.AnswerMapper">
|
||||
|
||||
<resultMap id="answerResultMap" type="sgis.surveysystem.domain.Answer">
|
||||
<id property="answerId" column="answer_id"/>
|
||||
<result property="responseId" column="response_id"/>
|
||||
<result property="questionId" column="question_id"/>
|
||||
<result property="answerText" column="answer_text"/>
|
||||
<result property="selectedOptionId" column="selected_option_id"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertAnswer" parameterType="sgis.surveysystem.domain.Answer">
|
||||
INSERT INTO tb_answers (
|
||||
answer_id,
|
||||
response_id,
|
||||
question_id,
|
||||
answer_text,
|
||||
selected_option_id
|
||||
) VALUES (
|
||||
#{answerId, jdbcType=OTHER},
|
||||
#{responseId, jdbcType=OTHER},
|
||||
#{questionId, jdbcType=OTHER},
|
||||
#{answerText},
|
||||
#{selectedOptionId, jdbcType=OTHER}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findAnswerById" resultMap="answerResultMap">
|
||||
SELECT
|
||||
answer_id,
|
||||
response_id,
|
||||
question_id,
|
||||
answer_text,
|
||||
selected_option_id
|
||||
FROM tb_answers
|
||||
WHERE answer_id = #{answerId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<select id="findAnswersByResponseId" resultMap="answerResultMap">
|
||||
SELECT
|
||||
answer_id,
|
||||
response_id,
|
||||
question_id,
|
||||
answer_text,
|
||||
selected_option_id
|
||||
FROM tb_answers
|
||||
WHERE response_id = #{responseId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<select id="findAnswersByQuestionId" resultMap="answerResultMap">
|
||||
SELECT
|
||||
answer_id,
|
||||
response_id,
|
||||
question_id,
|
||||
answer_text,
|
||||
selected_option_id
|
||||
FROM tb_answers
|
||||
WHERE question_id = #{questionId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<update id="updateAnswer" parameterType="sgis.surveysystem.domain.Answer">
|
||||
UPDATE tb_answers
|
||||
SET
|
||||
answer_text = #{answerText},
|
||||
selected_option_id = #{selectedOptionId, jdbcType=OTHER}
|
||||
WHERE answer_id = #{answerId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<delete id="deleteAnswer">
|
||||
DELETE FROM tb_answers
|
||||
WHERE answer_id = #{answerId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.AnswerSelectedOptionMapper">
|
||||
|
||||
<resultMap id="answerSelectedOptionResultMap" type="sgis.surveysystem.domain.AnswerSelectedOption">
|
||||
<id property="answerId" column="answer_id"/>
|
||||
<id property="optionId" column="option_id"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertAnswerSelectedOption" parameterType="sgis.surveysystem.domain.AnswerSelectedOption">
|
||||
INSERT INTO tb_answer_selected_options (
|
||||
answer_id,
|
||||
option_id
|
||||
) VALUES (
|
||||
#{answerId, jdbcType=OTHER},
|
||||
#{optionId, jdbcType=OTHER}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<insert id="insertMultipleAnswerSelectedOptions" parameterType="java.util.List">
|
||||
INSERT INTO tb_answer_selected_options (
|
||||
answer_id,
|
||||
option_id
|
||||
) VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(
|
||||
#{item.answerId, jdbcType=OTHER},
|
||||
#{item.optionId, jdbcType=OTHER}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<select id="findOptionsByAnswerId" resultMap="answerSelectedOptionResultMap">
|
||||
SELECT
|
||||
answer_id,
|
||||
option_id
|
||||
FROM tb_answer_selected_options
|
||||
WHERE answer_id = #{answerId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<delete id="deleteByAnswerId">
|
||||
DELETE FROM tb_answer_selected_options
|
||||
WHERE answer_id = #{answerId, jdbcType=OTHER}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteAnswerSelectedOption">
|
||||
DELETE FROM tb_answer_selected_options
|
||||
WHERE answer_id = #{param1, jdbcType=OTHER} AND option_id = #{param2, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.QuestionMapper">
|
||||
|
||||
<resultMap id="questionResultMap" type="sgis.surveysystem.domain.Question">
|
||||
<id property="questionId" column="question_id"/>
|
||||
<result property="surveyId" column="survey_id"/>
|
||||
<result property="questionText" column="question_text"/>
|
||||
<result property="questionType" column="question_type"/>
|
||||
<result property="questionOrder" column="question_order"/>
|
||||
<result property="isRequired" column="is_required"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 문항 삽입 -->
|
||||
<insert id="insertQuestion" parameterType="sgis.surveysystem.domain.Question">
|
||||
INSERT INTO tb_questions (
|
||||
question_id,
|
||||
survey_id,
|
||||
question_text,
|
||||
question_type,
|
||||
question_order,
|
||||
is_required
|
||||
) VALUES (
|
||||
#{questionId, jdbcType=OTHER},
|
||||
#{surveyId, jdbcType=OTHER},
|
||||
#{questionText},
|
||||
#{questionType},
|
||||
#{questionOrder},
|
||||
#{isRequired}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 설문 ID로 문항 목록 조회 -->
|
||||
<select id="findQuestionsBySurveyId" resultMap="questionResultMap">
|
||||
SELECT
|
||||
question_id,
|
||||
survey_id,
|
||||
question_text,
|
||||
question_type,
|
||||
question_order,
|
||||
is_required
|
||||
FROM tb_questions
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
ORDER BY question_order ASC
|
||||
</select>
|
||||
|
||||
<!-- ID로 특정 문항 조회 -->
|
||||
<select id="findQuestionById" resultMap="questionResultMap">
|
||||
SELECT
|
||||
question_id,
|
||||
survey_id,
|
||||
question_text,
|
||||
question_type,
|
||||
question_order,
|
||||
is_required
|
||||
FROM tb_questions
|
||||
WHERE question_id = #{questionId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<!-- 문항 업데이트 -->
|
||||
<update id="updateQuestion" parameterType="sgis.surveysystem.domain.Question">
|
||||
UPDATE tb_questions
|
||||
SET
|
||||
question_text = #{questionText},
|
||||
question_type = #{questionType},
|
||||
question_order = #{questionOrder},
|
||||
is_required = #{isRequired}
|
||||
WHERE question_id = #{questionId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<!-- 문항 삭제 -->
|
||||
<delete id="deleteQuestion">
|
||||
DELETE FROM tb_questions
|
||||
WHERE question_id = #{questionId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.QuestionOptionMapper">
|
||||
|
||||
<resultMap id="questionOptionResultMap" type="sgis.surveysystem.domain.QuestionOption">
|
||||
<id property="optionId" column="option_id"/>
|
||||
<result property="questionId" column="question_id"/>
|
||||
<result property="optionText" column="option_text"/>
|
||||
<result property="optionOrder" column="option_order"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertQuestionOption" parameterType="sgis.surveysystem.domain.QuestionOption">
|
||||
INSERT INTO tb_question_options (
|
||||
option_id,
|
||||
question_id,
|
||||
option_text,
|
||||
option_order
|
||||
) VALUES (
|
||||
#{optionId, jdbcType=OTHER},
|
||||
#{questionId, jdbcType=OTHER},
|
||||
#{optionText},
|
||||
#{optionOrder}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findOptionsByQuestionId" resultMap="questionOptionResultMap">
|
||||
SELECT
|
||||
option_id,
|
||||
question_id,
|
||||
option_text,
|
||||
option_order
|
||||
FROM tb_question_options
|
||||
WHERE question_id = #{questionId, jdbcType=OTHER}
|
||||
ORDER BY option_order ASC
|
||||
</select>
|
||||
|
||||
<select id="findQuestionOptionById" resultMap="questionOptionResultMap">
|
||||
SELECT
|
||||
option_id,
|
||||
question_id,
|
||||
option_text,
|
||||
option_order
|
||||
FROM tb_question_options
|
||||
WHERE option_id = #{optionId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<update id="updateQuestionOption" parameterType="sgis.surveysystem.domain.QuestionOption">
|
||||
UPDATE tb_question_options
|
||||
SET
|
||||
option_text = #{optionText},
|
||||
option_order = #{optionOrder}
|
||||
WHERE option_id = #{optionId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<delete id="deleteQuestionOption">
|
||||
DELETE FROM tb_question_options
|
||||
WHERE option_id = #{optionId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.RespondentMapper">
|
||||
|
||||
<resultMap id="respondentResultMap" type="sgis.surveysystem.domain.Respondent">
|
||||
<id property="respondentId" column="respondent_id"/>
|
||||
<result property="userId" column="user_id"/>
|
||||
<result property="ipAddress" column="ip_address"/>
|
||||
<result property="responseStartAt" column="response_start_at"/>
|
||||
<result property="responseEndAt" column="response_end_at"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertRespondent" parameterType="sgis.surveysystem.domain.Respondent">
|
||||
INSERT INTO tb_respondents (
|
||||
respondent_id,
|
||||
user_id,
|
||||
ip_address,
|
||||
response_start_at,
|
||||
response_end_at
|
||||
) VALUES (
|
||||
#{respondentId, jdbcType=OTHER},
|
||||
#{userId},
|
||||
#{ipAddress, jdbcType=OTHER},
|
||||
#{responseStartAt},
|
||||
#{responseEndAt}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findRespondentById" resultMap="respondentResultMap">
|
||||
SELECT
|
||||
respondent_id,
|
||||
user_id,
|
||||
ip_address,
|
||||
response_start_at,
|
||||
response_end_at
|
||||
FROM tb_respondents
|
||||
WHERE respondent_id = #{respondentId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<select id="findRespondentByUserId" resultMap="respondentResultMap">
|
||||
SELECT
|
||||
respondent_id,
|
||||
user_id,
|
||||
ip_address,
|
||||
response_start_at,
|
||||
response_end_at
|
||||
FROM tb_respondents
|
||||
WHERE user_id = #{userId}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<update id="updateRespondent" parameterType="sgis.surveysystem.domain.Respondent">
|
||||
UPDATE tb_respondents
|
||||
SET
|
||||
user_id = #{userId},
|
||||
ip_address = #{ipAddress, jdbcType=OTHER},
|
||||
response_start_at = #{responseStartAt},
|
||||
response_end_at = #{responseEndAt}
|
||||
WHERE respondent_id = #{respondentId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<delete id="deleteRespondent">
|
||||
DELETE FROM tb_respondents
|
||||
WHERE respondent_id = #{respondentId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.SurveyMapper">
|
||||
|
||||
<resultMap id="surveyResultMap" type="sgis.surveysystem.domain.Survey">
|
||||
<id property="surveyId" column="survey_id"/>
|
||||
<result property="surveyTitle" column="survey_title"/>
|
||||
<result property="surveyDescription" column="survey_description"/>
|
||||
<result property="createdAt" column="created_at"/>
|
||||
<result property="updatedAt" column="updated_at"/>
|
||||
<result property="isActive" column="is_active"/>
|
||||
<result property="startDate" column="start_date"/>
|
||||
<result property="endDate" column="end_date"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertSurvey" parameterType="sgis.surveysystem.domain.Survey">
|
||||
INSERT INTO tb_surveys (
|
||||
survey_id,
|
||||
survey_title,
|
||||
survey_description,
|
||||
created_at,
|
||||
updated_at,
|
||||
is_active,
|
||||
start_date,
|
||||
end_date
|
||||
) VALUES (
|
||||
#{surveyId, jdbcType=OTHER}, #{surveyTitle},
|
||||
#{surveyDescription},
|
||||
#{createdAt},
|
||||
#{updatedAt},
|
||||
#{isActive},
|
||||
#{startDate},
|
||||
#{endDate}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findAllSurveys" resultMap="surveyResultMap">
|
||||
SELECT
|
||||
survey_id,
|
||||
survey_title,
|
||||
survey_description,
|
||||
created_at,
|
||||
updated_at,
|
||||
is_active,
|
||||
start_date,
|
||||
end_date
|
||||
FROM tb_surveys
|
||||
</select>
|
||||
|
||||
<select id="findSurveyById" resultMap="surveyResultMap">
|
||||
SELECT
|
||||
survey_id,
|
||||
survey_description,
|
||||
survey_title,
|
||||
created_at,
|
||||
updated_at,
|
||||
is_active,
|
||||
start_date,
|
||||
end_date
|
||||
FROM tb_surveys
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<update id="updateSurvey" parameterType="sgis.surveysystem.domain.Survey">
|
||||
UPDATE tb_surveys
|
||||
SET
|
||||
survey_title = #{surveyTitle},
|
||||
survey_description = #{surveyDescription},
|
||||
updated_at = #{updatedAt},
|
||||
is_active = #{isActive},
|
||||
start_date = #{startDate},
|
||||
end_date = #{endDate}
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<update id="updateSurveyStatus">
|
||||
UPDATE tb_surveys
|
||||
SET
|
||||
is_active = #{isActive},
|
||||
updated_at = NOW()
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<delete id="deleteSurvey">
|
||||
DELETE FROM tb_surveys
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.SurveyResponseMapper">
|
||||
|
||||
<resultMap id="surveyResponseResultMap" type="sgis.surveysystem.domain.SurveyResponse">
|
||||
<id property="responseId" column="response_id"/>
|
||||
<result property="surveyId" column="survey_id"/>
|
||||
<result property="respondentId" column="respondent_id"/>
|
||||
<result property="submittedAt" column="submitted_at"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertSurveyResponse" parameterType="sgis.surveysystem.domain.SurveyResponse">
|
||||
INSERT INTO tb_survey_responses (
|
||||
response_id,
|
||||
survey_id,
|
||||
respondent_id,
|
||||
submitted_at
|
||||
) VALUES (
|
||||
#{responseId, jdbcType=OTHER},
|
||||
#{surveyId, jdbcType=OTHER},
|
||||
#{respondentId, jdbcType=OTHER},
|
||||
#{submittedAt}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findSurveyResponseById" resultMap="surveyResponseResultMap">
|
||||
SELECT
|
||||
response_id,
|
||||
survey_id,
|
||||
respondent_id,
|
||||
submitted_at
|
||||
FROM tb_survey_responses
|
||||
WHERE response_id = #{responseId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<select id="findResponsesBySurveyId" resultMap="surveyResponseResultMap">
|
||||
SELECT
|
||||
response_id,
|
||||
survey_id,
|
||||
respondent_id,
|
||||
submitted_at
|
||||
FROM tb_survey_responses
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
ORDER BY submitted_at DESC
|
||||
</select>
|
||||
|
||||
<select id="findResponsesByRespondentId" resultMap="surveyResponseResultMap">
|
||||
SELECT
|
||||
response_id,
|
||||
survey_id,
|
||||
respondent_id,
|
||||
submitted_at
|
||||
FROM tb_survey_responses
|
||||
WHERE respondent_id = #{respondentId, jdbcType=OTHER}
|
||||
ORDER BY submitted_at DESC
|
||||
</select>
|
||||
|
||||
<delete id="deleteSurveyResponse">
|
||||
DELETE FROM tb_survey_responses
|
||||
WHERE response_id = #{responseId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -19,6 +19,8 @@
|
|||
<property name="typeHandlers">
|
||||
<array>
|
||||
<bean class="sgis.board.typehandler.OffsetDateTimeTypeHandler" />
|
||||
<bean class="sgis.surveysystem.config.UUIDTypeHandler" />
|
||||
<bean class="sgis.surveysystem.config.LocalDateTimeTypeHandler" />
|
||||
</array>
|
||||
</property>
|
||||
</bean>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -381,7 +381,7 @@
|
|||
</li>
|
||||
<li style="width: 400px;">
|
||||
<a href="javascript:showSichudan();" id="borehole-profile" class="btn btn-ske-blue btn-icon-left btn-icon-search" autocomplete="off" ><span>지반단면도</span></a>
|
||||
<a href="javascript:showSichudan();" id="borehole-log" class="btn btn-ske-blue btn-icon-left btn-icon-search" autocomplete="off" ><span>지반주상도</span></a>
|
||||
<a href="javascript:showBoreholeLog();" id="borehole-log" class="btn btn-ske-blue btn-icon-left btn-icon-search" autocomplete="off" ><span>지반주상도</span></a>
|
||||
<script>
|
||||
|
||||
function showSichudan() {
|
||||
|
|
@ -389,11 +389,28 @@
|
|||
if (codes == "") {
|
||||
alert("시추공을 선택해주세요.");
|
||||
return;
|
||||
} else if(codes.indexOf('undefined') != -1 ) {
|
||||
alert("시추공이 존재하지 않는 사업입니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
var sichuWin = window.open("/map/sichudanNew.do?code=" + codes, "sichuWin", "scrollbars=no,titlebar=no,width=1024,height=740,left=0,top=0", true);
|
||||
sichuWin.focus();
|
||||
}
|
||||
|
||||
function showBoreholeLog() {
|
||||
var codes = getSelectHoleInfo();
|
||||
if (codes == "") {
|
||||
alert("시추공을 선택해주세요.");
|
||||
return;
|
||||
} else if(codes.indexOf('undefined') != -1 ) {
|
||||
alert("시추공이 존재하지 않는 사업입니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
var sichuWin = window.open("/map/borehole-log.do?code=" + codes, "Borehole log", "scrollbars=no,titlebar=no,width=1024,height=740,left=0,top=0", true);
|
||||
sichuWin.focus();
|
||||
}
|
||||
</script>
|
||||
</li>
|
||||
<li>
|
||||
|
|
@ -1022,6 +1039,7 @@
|
|||
</div>
|
||||
<!-- 팝업 끝 -->
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,192 @@
|
|||
설문 생성을 위한 관리자용 HTML 파일을 수정해 드릴게요. AJAX 요청 URL이 XXX.do 형식에 맞도록 업데이트했습니다.
|
||||
|
||||
createSurvey.jsp 수정 내용
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>설문 생성 (관리자)</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Malgun Gothic', '맑은 고딕', Arial, sans-serif;
|
||||
margin: 20px;
|
||||
background-color: #f4f4f4;
|
||||
color: #333;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.container {
|
||||
background-color: #fff;
|
||||
padding: 25px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
h2 {
|
||||
color: #0056b3;
|
||||
text-align: center;
|
||||
margin-bottom: 25px;
|
||||
font-size: 1.8em;
|
||||
border-bottom: 2px solid #eee;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.form-group {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
}
|
||||
.form-group input[type="text"],
|
||||
.form-group input[type="datetime-local"],
|
||||
.form-group textarea {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
font-size: 1em;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
.form-group input[type="text"]:focus,
|
||||
.form-group input[type="datetime-local"]:focus,
|
||||
.form-group textarea:focus {
|
||||
border-color: #007bff;
|
||||
outline: none;
|
||||
}
|
||||
.form-group textarea {
|
||||
resize: vertical;
|
||||
min-height: 100px;
|
||||
}
|
||||
button {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
padding: 12px 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 1.1em;
|
||||
width: 100%;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
margin-top: 10px;
|
||||
}
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
button:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.message {
|
||||
margin-top: 25px;
|
||||
padding: 12px;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
display: none;
|
||||
word-break: break-all;
|
||||
}
|
||||
.message.success {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
border: 1px solid #c3e6cb;
|
||||
}
|
||||
.message.error {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>새 설문 생성</h2>
|
||||
<form id="createSurveyForm">
|
||||
<div class="form-group">
|
||||
<label for="surveyTitle">설문 제목:</label>
|
||||
<input type="text" id="surveyTitle" name="surveyTitle" placeholder="예: 2025년 시스템 만족도 설문" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="surveyDescription">설문 설명:</label>
|
||||
<textarea id="surveyDescription" name="surveyDescription" placeholder="설문에 대한 자세한 설명을 입력하세요."></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="startDate">시작일시:</label>
|
||||
<input type="datetime-local" id="startDate" name="startDate">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="endDate">종료일시:</label>
|
||||
<input type="datetime-local" id="endDate" name="endDate">
|
||||
</div>
|
||||
|
||||
<button type="submit">설문 생성</button>
|
||||
</form>
|
||||
<div id="message" class="message"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('createSurveyForm').addEventListener('submit', async function(event) {
|
||||
event.preventDefault(); // 폼의 기본 제출 동작 방지
|
||||
|
||||
const messageDiv = document.getElementById('message');
|
||||
messageDiv.style.display = 'none'; // 이전 메시지 숨기기
|
||||
messageDiv.classList.remove('success', 'error'); // 이전 스타일 클래스 제거
|
||||
|
||||
// 폼 필드에서 데이터 수집
|
||||
const formData = {
|
||||
surveyTitle: document.getElementById('surveyTitle').value,
|
||||
surveyDescription: document.getElementById('surveyDescription').value,
|
||||
// datetime-local 입력은 값이 없으면 빈 문자열이 되므로, null로 변환
|
||||
startDate: document.getElementById('startDate').value ? document.getElementById('startDate').value + ':00' : null, // 초까지 포함하도록 포맷팅
|
||||
endDate: document.getElementById('endDate').value ? document.getElementById('endDate').value + ':00' : null // 초까지 포함하도록 포맷팅
|
||||
};
|
||||
|
||||
// eGovFrame 환경에서 컨텍스트 경로를 동적으로 가져오는 방법 (JSP 파일일 경우)
|
||||
// HTML 파일에서는 직접 경로를 지정하거나, 웹 서버 설정에 따라 /api/surveys로 직접 접근 가능
|
||||
const contextPath = "<%= request.getContextPath() %>"; // JSP일 경우에만 작동
|
||||
// SurveyController의 @RequestMapping("/api/surveys")와 @PostMapping("/createSurvey.do")를 결합
|
||||
const apiUrl = (typeof contextPath !== 'undefined' && contextPath !== null && contextPath !== '') ? contextPath + '/api/surveys/createSurvey.do' : '/api/surveys/createSurvey.do';
|
||||
|
||||
|
||||
try {
|
||||
const response = await fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(formData) // JSON 문자열로 변환하여 전송
|
||||
});
|
||||
|
||||
if (response.ok) { // HTTP 상태 코드가 200-299 범위인 경우 (성공)
|
||||
const result = await response.json(); // 응답 본문을 JSON으로 파싱
|
||||
messageDiv.textContent = '설문이 성공적으로 생성되었습니다! (ID: ' + result.surveyId + ')';
|
||||
messageDiv.classList.add('success');
|
||||
messageDiv.style.display = 'block';
|
||||
this.reset(); // 폼 필드 초기화
|
||||
} else { // HTTP 상태 코드가 200-299 범위를 벗어난 경우 (실패)
|
||||
const errorText = await response.text(); // 오류 메시지를 텍스트로 가져옴
|
||||
messageDiv.textContent = '설문 생성 실패: ' + (errorText || '알 수 없는 오류');
|
||||
messageDiv.classList.add('error');
|
||||
messageDiv.style.display = 'block';
|
||||
}
|
||||
} catch (error) {
|
||||
// 네트워크 오류 또는 fetch 요청 자체의 문제 발생 시
|
||||
console.error('네트워크 오류:', error);
|
||||
messageDiv.textContent = '네트워크 오류가 발생했습니다. 다시 시도해주세요.';
|
||||
messageDiv.classList.add('error');
|
||||
messageDiv.style.display = 'block';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -57,7 +57,15 @@ var predictionGraphInfoPopup;
|
|||
var predictionGraphInfoPopupData;
|
||||
//var url = 'http://210.120.6.116:9999';
|
||||
//var GEOSERVER_URL = 'https://geoserver.smart.dbnt.co.kr';
|
||||
var GEOSERVER_URL = 'http://localhost:9000';
|
||||
var GEOSERVER_URL = '/wms';
|
||||
|
||||
//현재 도메인을 가져옵니다.
|
||||
var currentDomain = window.location.hostname;
|
||||
|
||||
//현재 도메인이 'localhost' 또는 '127.0.0.1'을 포함하는지 확인합니다.
|
||||
if (currentDomain.includes('localhost') || currentDomain.includes('127.0.0.1')) {
|
||||
GEOSERVER_URL = 'http://10.dbnt.co.kr:9000';
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
// 지도 서비스 실행
|
||||
|
|
@ -333,6 +341,8 @@ function init() {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------
|
||||
|
|
|
|||
|
|
@ -514,4 +514,54 @@ FROM (SELECT ROWNUM RNK,
|
|||
</foreach>
|
||||
|
||||
</select>
|
||||
|
||||
<select id="mapBoreholeLogHeader" parameterType="map" resultType="egovMap">
|
||||
SELECT
|
||||
ap.project_code,
|
||||
hole.hole_code AS HOLE_CODE,
|
||||
ap.project_name,
|
||||
cc1.code_txt ||
|
||||
CASE
|
||||
WHEN cc2.code_txt IS NOT NULL THEN ' ' || cc2.code_txt
|
||||
ELSE ''
|
||||
END AS COMPANY,
|
||||
hole.hole_name AS HOLE_NAME,
|
||||
cc3.code_txt AS DISTRICT,
|
||||
hole.hole_x AS HOLE_OR_X,
|
||||
hole.hole_y AS HOLE_OR_Y,
|
||||
hole.HOLE_ELEVATION AS HOLE_EL,
|
||||
hole.HOLE_END_DATE AS HOLE_DATE_TO,
|
||||
hole.HOLE_DRILLING_DEPTH AS HOLE_TOTAL_DEPTH,
|
||||
hole.HOLE_CASING_DEPTH AS HOLE_CASING_DEPTH,
|
||||
hole.HOLE_WATER_LEVEL AS hole_wl,
|
||||
hole.HOLE_BORING_MACHINE AS HOLE_BORING_MACHINE,
|
||||
hole.HOLE_BORING_METHOD AS HOLE_BORING_METHOD,
|
||||
hole.HOLE_BORING_NAME AS HOLE_BORING_BY,
|
||||
'N/A' AS HOLE_INSPECTED_BY,
|
||||
REPLACE((epsg_code.code_txt || ' ' || epsg_code2.code_txt), '(BESSEL)','') AS COORDINATE_L,
|
||||
(
|
||||
SELECT
|
||||
CASE
|
||||
WHEN MAX(layer.LAYER_DEPTH_TO::NUMERIC) >= 34.6 THEN 3
|
||||
WHEN MAX(layer.LAYER_DEPTH_TO::NUMERIC) >= 17.3 THEN 2
|
||||
ELSE 1
|
||||
END
|
||||
FROM APPTB_LAYR01 layer
|
||||
WHERE layer.business_code = hole.business_code -- 현재 행의 business_code 사용
|
||||
AND layer.hole_code = hole.hole_code -- 현재 행의 hole_code 사용
|
||||
) AS PAGE_NUM
|
||||
FROM APPTB_HOLE01 hole
|
||||
LEFT JOIN APPTB_SAUP01 business ON hole.business_code = business.business_code
|
||||
LEFT JOIN APPTB_PROJ01 ap ON business.project_code = ap.project_code
|
||||
LEFT JOIN comtb_code02 cc1 ON ap.project_ordering_code = cc1.code_val
|
||||
LEFT JOIN comtb_code02 cc2 ON ap.project_affiliated_code = cc2.code_val
|
||||
LEFT JOIN comtb_code02 cc3 ON ap.project_harbor_code = cc3.code_val
|
||||
LEFT JOIN comtb_code02 epsg_code ON ap.PROJECT_EPSG_CODE = epsg_code.code_val
|
||||
LEFT JOIN comtb_code02 epsg_code2 ON hole.hole_coordinate = epsg_code2.code_val
|
||||
WHERE
|
||||
hole.business_code = #{businessCode} AND
|
||||
hole.hole_code = #{holeCode}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.AnswerMapper">
|
||||
|
||||
<resultMap id="answerResultMap" type="sgis.surveysystem.domain.Answer">
|
||||
<id property="answerId" column="answer_id"/>
|
||||
<result property="responseId" column="response_id"/>
|
||||
<result property="questionId" column="question_id"/>
|
||||
<result property="answerText" column="answer_text"/>
|
||||
<result property="selectedOptionId" column="selected_option_id"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertAnswer" parameterType="sgis.surveysystem.domain.Answer">
|
||||
INSERT INTO tb_answers (
|
||||
answer_id,
|
||||
response_id,
|
||||
question_id,
|
||||
answer_text,
|
||||
selected_option_id
|
||||
) VALUES (
|
||||
#{answerId, jdbcType=OTHER},
|
||||
#{responseId, jdbcType=OTHER},
|
||||
#{questionId, jdbcType=OTHER},
|
||||
#{answerText},
|
||||
#{selectedOptionId, jdbcType=OTHER}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findAnswerById" resultMap="answerResultMap">
|
||||
SELECT
|
||||
answer_id,
|
||||
response_id,
|
||||
question_id,
|
||||
answer_text,
|
||||
selected_option_id
|
||||
FROM tb_answers
|
||||
WHERE answer_id = #{answerId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<select id="findAnswersByResponseId" resultMap="answerResultMap">
|
||||
SELECT
|
||||
answer_id,
|
||||
response_id,
|
||||
question_id,
|
||||
answer_text,
|
||||
selected_option_id
|
||||
FROM tb_answers
|
||||
WHERE response_id = #{responseId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<select id="findAnswersByQuestionId" resultMap="answerResultMap">
|
||||
SELECT
|
||||
answer_id,
|
||||
response_id,
|
||||
question_id,
|
||||
answer_text,
|
||||
selected_option_id
|
||||
FROM tb_answers
|
||||
WHERE question_id = #{questionId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<update id="updateAnswer" parameterType="sgis.surveysystem.domain.Answer">
|
||||
UPDATE tb_answers
|
||||
SET
|
||||
answer_text = #{answerText},
|
||||
selected_option_id = #{selectedOptionId, jdbcType=OTHER}
|
||||
WHERE answer_id = #{answerId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<delete id="deleteAnswer">
|
||||
DELETE FROM tb_answers
|
||||
WHERE answer_id = #{answerId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.AnswerSelectedOptionMapper">
|
||||
|
||||
<resultMap id="answerSelectedOptionResultMap" type="sgis.surveysystem.domain.AnswerSelectedOption">
|
||||
<id property="answerId" column="answer_id"/>
|
||||
<id property="optionId" column="option_id"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertAnswerSelectedOption" parameterType="sgis.surveysystem.domain.AnswerSelectedOption">
|
||||
INSERT INTO tb_answer_selected_options (
|
||||
answer_id,
|
||||
option_id
|
||||
) VALUES (
|
||||
#{answerId, jdbcType=OTHER},
|
||||
#{optionId, jdbcType=OTHER}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<insert id="insertMultipleAnswerSelectedOptions" parameterType="java.util.List">
|
||||
INSERT INTO tb_answer_selected_options (
|
||||
answer_id,
|
||||
option_id
|
||||
) VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(
|
||||
#{item.answerId, jdbcType=OTHER},
|
||||
#{item.optionId, jdbcType=OTHER}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<select id="findOptionsByAnswerId" resultMap="answerSelectedOptionResultMap">
|
||||
SELECT
|
||||
answer_id,
|
||||
option_id
|
||||
FROM tb_answer_selected_options
|
||||
WHERE answer_id = #{answerId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<delete id="deleteByAnswerId">
|
||||
DELETE FROM tb_answer_selected_options
|
||||
WHERE answer_id = #{answerId, jdbcType=OTHER}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteAnswerSelectedOption">
|
||||
DELETE FROM tb_answer_selected_options
|
||||
WHERE answer_id = #{param1, jdbcType=OTHER} AND option_id = #{param2, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.QuestionMapper">
|
||||
|
||||
<resultMap id="questionResultMap" type="sgis.surveysystem.domain.Question">
|
||||
<id property="questionId" column="question_id"/>
|
||||
<result property="surveyId" column="survey_id"/>
|
||||
<result property="questionText" column="question_text"/>
|
||||
<result property="questionType" column="question_type"/>
|
||||
<result property="questionOrder" column="question_order"/>
|
||||
<result property="isRequired" column="is_required"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 문항 삽입 -->
|
||||
<insert id="insertQuestion" parameterType="sgis.surveysystem.domain.Question">
|
||||
INSERT INTO tb_questions (
|
||||
question_id,
|
||||
survey_id,
|
||||
question_text,
|
||||
question_type,
|
||||
question_order,
|
||||
is_required
|
||||
) VALUES (
|
||||
#{questionId, jdbcType=OTHER},
|
||||
#{surveyId, jdbcType=OTHER},
|
||||
#{questionText},
|
||||
#{questionType},
|
||||
#{questionOrder},
|
||||
#{isRequired}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 설문 ID로 문항 목록 조회 -->
|
||||
<select id="findQuestionsBySurveyId" resultMap="questionResultMap">
|
||||
SELECT
|
||||
question_id,
|
||||
survey_id,
|
||||
question_text,
|
||||
question_type,
|
||||
question_order,
|
||||
is_required
|
||||
FROM tb_questions
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
ORDER BY question_order ASC
|
||||
</select>
|
||||
|
||||
<!-- ID로 특정 문항 조회 -->
|
||||
<select id="findQuestionById" resultMap="questionResultMap">
|
||||
SELECT
|
||||
question_id,
|
||||
survey_id,
|
||||
question_text,
|
||||
question_type,
|
||||
question_order,
|
||||
is_required
|
||||
FROM tb_questions
|
||||
WHERE question_id = #{questionId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<!-- 문항 업데이트 -->
|
||||
<update id="updateQuestion" parameterType="sgis.surveysystem.domain.Question">
|
||||
UPDATE tb_questions
|
||||
SET
|
||||
question_text = #{questionText},
|
||||
question_type = #{questionType},
|
||||
question_order = #{questionOrder},
|
||||
is_required = #{isRequired}
|
||||
WHERE question_id = #{questionId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<!-- 문항 삭제 -->
|
||||
<delete id="deleteQuestion">
|
||||
DELETE FROM tb_questions
|
||||
WHERE question_id = #{questionId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.QuestionOptionMapper">
|
||||
|
||||
<resultMap id="questionOptionResultMap" type="sgis.surveysystem.domain.QuestionOption">
|
||||
<id property="optionId" column="option_id"/>
|
||||
<result property="questionId" column="question_id"/>
|
||||
<result property="optionText" column="option_text"/>
|
||||
<result property="optionOrder" column="option_order"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertQuestionOption" parameterType="sgis.surveysystem.domain.QuestionOption">
|
||||
INSERT INTO tb_question_options (
|
||||
option_id,
|
||||
question_id,
|
||||
option_text,
|
||||
option_order
|
||||
) VALUES (
|
||||
#{optionId, jdbcType=OTHER},
|
||||
#{questionId, jdbcType=OTHER},
|
||||
#{optionText},
|
||||
#{optionOrder}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findOptionsByQuestionId" resultMap="questionOptionResultMap">
|
||||
SELECT
|
||||
option_id,
|
||||
question_id,
|
||||
option_text,
|
||||
option_order
|
||||
FROM tb_question_options
|
||||
WHERE question_id = #{questionId, jdbcType=OTHER}
|
||||
ORDER BY option_order ASC
|
||||
</select>
|
||||
|
||||
<select id="findQuestionOptionById" resultMap="questionOptionResultMap">
|
||||
SELECT
|
||||
option_id,
|
||||
question_id,
|
||||
option_text,
|
||||
option_order
|
||||
FROM tb_question_options
|
||||
WHERE option_id = #{optionId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<update id="updateQuestionOption" parameterType="sgis.surveysystem.domain.QuestionOption">
|
||||
UPDATE tb_question_options
|
||||
SET
|
||||
option_text = #{optionText},
|
||||
option_order = #{optionOrder}
|
||||
WHERE option_id = #{optionId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<delete id="deleteQuestionOption">
|
||||
DELETE FROM tb_question_options
|
||||
WHERE option_id = #{optionId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.RespondentMapper">
|
||||
|
||||
<resultMap id="respondentResultMap" type="sgis.surveysystem.domain.Respondent">
|
||||
<id property="respondentId" column="respondent_id"/>
|
||||
<result property="userId" column="user_id"/>
|
||||
<result property="ipAddress" column="ip_address"/>
|
||||
<result property="responseStartAt" column="response_start_at"/>
|
||||
<result property="responseEndAt" column="response_end_at"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertRespondent" parameterType="sgis.surveysystem.domain.Respondent">
|
||||
INSERT INTO tb_respondents (
|
||||
respondent_id,
|
||||
user_id,
|
||||
ip_address,
|
||||
response_start_at,
|
||||
response_end_at
|
||||
) VALUES (
|
||||
#{respondentId, jdbcType=OTHER},
|
||||
#{userId},
|
||||
#{ipAddress, jdbcType=OTHER},
|
||||
#{responseStartAt},
|
||||
#{responseEndAt}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findRespondentById" resultMap="respondentResultMap">
|
||||
SELECT
|
||||
respondent_id,
|
||||
user_id,
|
||||
ip_address,
|
||||
response_start_at,
|
||||
response_end_at
|
||||
FROM tb_respondents
|
||||
WHERE respondent_id = #{respondentId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<select id="findRespondentByUserId" resultMap="respondentResultMap">
|
||||
SELECT
|
||||
respondent_id,
|
||||
user_id,
|
||||
ip_address,
|
||||
response_start_at,
|
||||
response_end_at
|
||||
FROM tb_respondents
|
||||
WHERE user_id = #{userId}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<update id="updateRespondent" parameterType="sgis.surveysystem.domain.Respondent">
|
||||
UPDATE tb_respondents
|
||||
SET
|
||||
user_id = #{userId},
|
||||
ip_address = #{ipAddress, jdbcType=OTHER},
|
||||
response_start_at = #{responseStartAt},
|
||||
response_end_at = #{responseEndAt}
|
||||
WHERE respondent_id = #{respondentId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<delete id="deleteRespondent">
|
||||
DELETE FROM tb_respondents
|
||||
WHERE respondent_id = #{respondentId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.SurveyMapper">
|
||||
|
||||
<resultMap id="surveyResultMap" type="sgis.surveysystem.domain.Survey">
|
||||
<id property="surveyId" column="survey_id"/>
|
||||
<result property="surveyTitle" column="survey_title"/>
|
||||
<result property="surveyDescription" column="survey_description"/>
|
||||
<result property="createdAt" column="created_at"/>
|
||||
<result property="updatedAt" column="updated_at"/>
|
||||
<result property="isActive" column="is_active"/>
|
||||
<result property="startDate" column="start_date"/>
|
||||
<result property="endDate" column="end_date"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertSurvey" parameterType="sgis.surveysystem.domain.Survey">
|
||||
INSERT INTO tb_surveys (
|
||||
survey_id,
|
||||
survey_title,
|
||||
survey_description,
|
||||
created_at,
|
||||
updated_at,
|
||||
is_active,
|
||||
start_date,
|
||||
end_date
|
||||
) VALUES (
|
||||
#{surveyId, jdbcType=OTHER}, #{surveyTitle},
|
||||
#{surveyDescription},
|
||||
#{createdAt},
|
||||
#{updatedAt},
|
||||
#{isActive},
|
||||
#{startDate},
|
||||
#{endDate}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findAllSurveys" resultMap="surveyResultMap">
|
||||
SELECT
|
||||
survey_id,
|
||||
survey_title,
|
||||
survey_description,
|
||||
created_at,
|
||||
updated_at,
|
||||
is_active,
|
||||
start_date,
|
||||
end_date
|
||||
FROM tb_surveys
|
||||
</select>
|
||||
|
||||
<select id="findSurveyById" resultMap="surveyResultMap">
|
||||
SELECT
|
||||
survey_id,
|
||||
survey_description,
|
||||
survey_title,
|
||||
created_at,
|
||||
updated_at,
|
||||
is_active,
|
||||
start_date,
|
||||
end_date
|
||||
FROM tb_surveys
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<update id="updateSurvey" parameterType="sgis.surveysystem.domain.Survey">
|
||||
UPDATE tb_surveys
|
||||
SET
|
||||
survey_title = #{surveyTitle},
|
||||
survey_description = #{surveyDescription},
|
||||
updated_at = #{updatedAt},
|
||||
is_active = #{isActive},
|
||||
start_date = #{startDate},
|
||||
end_date = #{endDate}
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<update id="updateSurveyStatus">
|
||||
UPDATE tb_surveys
|
||||
SET
|
||||
is_active = #{isActive},
|
||||
updated_at = NOW()
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
</update>
|
||||
|
||||
<delete id="deleteSurvey">
|
||||
DELETE FROM tb_surveys
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="sgis.surveysystem.mapper.SurveyResponseMapper">
|
||||
|
||||
<resultMap id="surveyResponseResultMap" type="sgis.surveysystem.domain.SurveyResponse">
|
||||
<id property="responseId" column="response_id"/>
|
||||
<result property="surveyId" column="survey_id"/>
|
||||
<result property="respondentId" column="respondent_id"/>
|
||||
<result property="submittedAt" column="submitted_at"/>
|
||||
</resultMap>
|
||||
|
||||
<insert id="insertSurveyResponse" parameterType="sgis.surveysystem.domain.SurveyResponse">
|
||||
INSERT INTO tb_survey_responses (
|
||||
response_id,
|
||||
survey_id,
|
||||
respondent_id,
|
||||
submitted_at
|
||||
) VALUES (
|
||||
#{responseId, jdbcType=OTHER},
|
||||
#{surveyId, jdbcType=OTHER},
|
||||
#{respondentId, jdbcType=OTHER},
|
||||
#{submittedAt}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findSurveyResponseById" resultMap="surveyResponseResultMap">
|
||||
SELECT
|
||||
response_id,
|
||||
survey_id,
|
||||
respondent_id,
|
||||
submitted_at
|
||||
FROM tb_survey_responses
|
||||
WHERE response_id = #{responseId, jdbcType=OTHER}
|
||||
</select>
|
||||
|
||||
<select id="findResponsesBySurveyId" resultMap="surveyResponseResultMap">
|
||||
SELECT
|
||||
response_id,
|
||||
survey_id,
|
||||
respondent_id,
|
||||
submitted_at
|
||||
FROM tb_survey_responses
|
||||
WHERE survey_id = #{surveyId, jdbcType=OTHER}
|
||||
ORDER BY submitted_at DESC
|
||||
</select>
|
||||
|
||||
<select id="findResponsesByRespondentId" resultMap="surveyResponseResultMap">
|
||||
SELECT
|
||||
response_id,
|
||||
survey_id,
|
||||
respondent_id,
|
||||
submitted_at
|
||||
FROM tb_survey_responses
|
||||
WHERE respondent_id = #{respondentId, jdbcType=OTHER}
|
||||
ORDER BY submitted_at DESC
|
||||
</select>
|
||||
|
||||
<delete id="deleteSurveyResponse">
|
||||
DELETE FROM tb_survey_responses
|
||||
WHERE response_id = #{responseId, jdbcType=OTHER}
|
||||
</delete>
|
||||
</mapper>
|
||||
|
|
@ -19,6 +19,8 @@
|
|||
<property name="typeHandlers">
|
||||
<array>
|
||||
<bean class="sgis.board.typehandler.OffsetDateTimeTypeHandler" />
|
||||
<bean class="sgis.surveysystem.config.UUIDTypeHandler" />
|
||||
<bean class="sgis.surveysystem.config.LocalDateTimeTypeHandler" />
|
||||
</array>
|
||||
</property>
|
||||
</bean>
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue