feat: 설문 back-end 코드 추가 건

master
thkim 2025-07-06 01:32:13 +09:00
parent 94fc429640
commit f0f09432c3
145 changed files with 5012 additions and 11 deletions

View File

@ -25,7 +25,6 @@
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v8.5 (2)"> <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"/> <attribute name="owner.project.facets" value="jst.web"/>
</attributes> </attributes>
</classpathentry> </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> <attributes>
<attribute name="owner.project.facets" value="java"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>

View File

@ -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\css\cross-section.css
src\main\webapp\com\js\cross-section.js src\main\webapp\com\js\cross-section.js
src\main\resources\egovframework\mapper\sgis\map\MapMainMapper.xml 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

View File

@ -306,6 +306,11 @@
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>2.12.5</version> <version>2.12.5</version>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.12.5</version>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId> <artifactId>jackson-annotations</artifactId>

View File

@ -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);
}
}

View File

@ -49,4 +49,6 @@ public interface MapMainMapper {
EgovMap selectWebDownloadLog(Map<String, Object> params) throws Exception; // dhlee 사용자별 다운로드 요청한 개수를 얻어온다. EgovMap selectWebDownloadLog(Map<String, Object> params) throws Exception; // dhlee 사용자별 다운로드 요청한 개수를 얻어온다.
List<EgovMap> selectProjectList(Map<String, Object> params) throws Exception; List<EgovMap> selectProjectList(Map<String, Object> params) throws Exception;
List<EgovMap> mapBoreholeLogHeader(Map<String, Object> params) throws Exception;
} }

View File

@ -50,4 +50,5 @@ public interface MapMainService {
List<EgovMap> selectProjectList(Map<String, Object> params) throws Exception; // dhlee List<EgovMap> selectProjectList(Map<String, Object> params) throws Exception; // dhlee
List<EgovMap> mapBoreholeLogList(Map<String, Object> params) throws Exception;
} }

View File

@ -117,4 +117,15 @@ public class MapMainServiceImpl implements MapMainService {
public List<EgovMap> selectProjectList(Map<String, Object> params) throws Exception { public List<EgovMap> selectProjectList(Map<String, Object> params) throws Exception {
return mapMainMapper.selectProjectList(params); 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;
}
} }

View File

@ -408,6 +408,31 @@ public class MapMainController extends BaseController {
return responseJson; 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 { public JSONObject getSectionData(String code) throws Exception {
code = code.trim(); code = code.trim();
@ -422,6 +447,10 @@ public class MapMainController extends BaseController {
EgovMap general = mapMainService.getGeneralData(params); EgovMap general = mapMainService.getGeneralData(params);
if( general == null ) {
// 예외처리 추가하기
}
String[] values = String.valueOf(general.get("vlu")).split("\\|"); String[] values = String.valueOf(general.get("vlu")).split("\\|");
JSONObject resultJson = new JSONObject(); JSONObject resultJson = new JSONObject();
@ -442,7 +471,11 @@ public class MapMainController extends BaseController {
resultJson.put("LL", position); resultJson.put("LL", position);
resultJson.put("PNAME", values[7]); resultJson.put("PNAME", values[7]);
resultJson.put("WATER", values[8]); if( 8 < values.length && values[8] != null ) {
resultJson.put("WATER", values[8]);
} else {
resultJson.put("WATER", "");
}
if (values.length == 10) { if (values.length == 10) {
resultJson.put("PCOM", values[9]); resultJson.put("PCOM", values[9]);

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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; // 객관식 다중 선택용
}

View File

@ -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();
}
}

View File

@ -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
}

View File

@ -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();
}
}

View File

@ -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 관련 별도 요청 사용 권장
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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 주소
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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); // 특정 선택 옵션 삭제
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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를 통해 답변에 연결된 모든 선택 옵션 삭제
}
}

View File

@ -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를 통해 답변 삭제
}
}

View File

@ -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를 통해 선택지 삭제
}
}

View File

@ -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를 통해 문항 삭제
}
}

View File

@ -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를 통해 응답자 삭제
}
}

View File

@ -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를 통해 응답 세션 삭제
}
}

View File

@ -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); // 업데이트된 상태로 반환
}
}

View File

@ -514,4 +514,54 @@ FROM (SELECT ROWNUM RNK,
</foreach> </foreach>
</select> </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> </mapper>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -19,7 +19,9 @@
<property name="typeHandlers"> <property name="typeHandlers">
<array> <array>
<bean class="sgis.board.typehandler.OffsetDateTimeTypeHandler" /> <bean class="sgis.board.typehandler.OffsetDateTimeTypeHandler" />
</array> <bean class="sgis.surveysystem.config.UUIDTypeHandler" />
<bean class="sgis.surveysystem.config.LocalDateTimeTypeHandler" />
</array>
</property> </property>
</bean> </bean>

File diff suppressed because it is too large Load Diff

View File

@ -381,7 +381,7 @@
</li> </li>
<li style="width: 400px;"> <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-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> <script>
function showSichudan() { function showSichudan() {
@ -389,11 +389,28 @@
if (codes == "") { if (codes == "") {
alert("시추공을 선택해주세요."); alert("시추공을 선택해주세요.");
return; 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); 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(); 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> </script>
</li> </li>
<li> <li>
@ -1001,7 +1018,7 @@
</div> </div>
<!-- 팝업 끝 --> <!-- 팝업 끝 -->
<!-- 팝업 시작 --> <!-- 팝업 시작 -->
<div id="watLevInfoPopup" class="kc-popup kc-popup-btn-group" style="display:none;"> <!--하단 버튼그룹 있는 팝업은 "kc-popup-btn-group" class 추가 --> <div id="watLevInfoPopup" class="kc-popup kc-popup-btn-group" style="display:none;"> <!--하단 버튼그룹 있는 팝업은 "kc-popup-btn-group" class 추가 -->
<div class="k-popup-edit-form button-group-display"> <div class="k-popup-edit-form button-group-display">
<div class="k-edit-form-container"> <div class="k-edit-form-container">
@ -1022,6 +1039,7 @@
</div> </div>
<!-- 팝업 끝 --> <!-- 팝업 끝 -->
</body> </body>
<script type="text/javascript"> <script type="text/javascript">

View File

@ -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>

View File

@ -57,7 +57,15 @@ var predictionGraphInfoPopup;
var predictionGraphInfoPopupData; var predictionGraphInfoPopupData;
//var url = 'http://210.120.6.116:9999'; //var url = 'http://210.120.6.116:9999';
//var GEOSERVER_URL = 'https://geoserver.smart.dbnt.co.kr'; //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(){ $(document).ready(function(){
// 지도 서비스 실행 // 지도 서비스 실행
@ -333,6 +341,8 @@ function init() {
} }
}); });
} }
//------------------------------------------- //-------------------------------------------

View File

@ -514,4 +514,54 @@ FROM (SELECT ROWNUM RNK,
</foreach> </foreach>
</select> </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> </mapper>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -19,7 +19,9 @@
<property name="typeHandlers"> <property name="typeHandlers">
<array> <array>
<bean class="sgis.board.typehandler.OffsetDateTimeTypeHandler" /> <bean class="sgis.board.typehandler.OffsetDateTimeTypeHandler" />
</array> <bean class="sgis.surveysystem.config.UUIDTypeHandler" />
<bean class="sgis.surveysystem.config.LocalDateTimeTypeHandler" />
</array>
</property> </property>
</bean> </bean>

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More