package kr.wisestone.owl.service.impl;
|
|
import com.google.common.collect.Lists;
|
import kr.wisestone.owl.common.ExcelConditionCheck;
|
import kr.wisestone.owl.constant.Constants;
|
import kr.wisestone.owl.constant.MsgConstants;
|
import kr.wisestone.owl.domain.CustomField;
|
import kr.wisestone.owl.domain.IssueCustomFieldValue;
|
import kr.wisestone.owl.domain.Workspace;
|
import kr.wisestone.owl.domain.enumType.CustomFieldType;
|
import kr.wisestone.owl.exception.OwlRuntimeException;
|
import kr.wisestone.owl.mapper.CustomFieldMapper;
|
import kr.wisestone.owl.repository.CustomFieldRepository;
|
import kr.wisestone.owl.service.*;
|
import kr.wisestone.owl.util.ConvertUtil;
|
import kr.wisestone.owl.util.MapUtil;
|
import kr.wisestone.owl.vo.*;
|
import kr.wisestone.owl.web.condition.CustomFieldCondition;
|
import kr.wisestone.owl.web.form.CustomFieldForm;
|
import kr.wisestone.owl.web.view.ExcelView;
|
import org.apache.commons.lang3.StringUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.ui.Model;
|
import org.springframework.web.servlet.ModelAndView;
|
import javax.servlet.http.HttpServletRequest;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
@Service
|
public class CustomFieldServiceImpl extends AbstractServiceImpl<CustomField, Long, JpaRepository<CustomField, Long>> implements CustomFieldService {
|
|
private static final Logger log = LoggerFactory.getLogger(CustomFieldServiceImpl.class);
|
|
public enum UseType {
|
Y,
|
N,
|
}
|
|
@Autowired
|
private CustomFieldRepository customFieldRepository;
|
|
@Autowired
|
private CustomFieldMapper customFieldMapper;
|
|
@Autowired
|
private WorkspaceService workspaceService;
|
|
@Autowired
|
private CustomFieldValueService customFieldValueService;
|
|
@Autowired
|
private IssueCustomFieldValueService issueCustomFieldValueService;
|
|
@Autowired
|
private UserService userService;
|
|
@Autowired
|
private ExcelView excelView;
|
|
@Autowired
|
private ExcelConditionCheck excelConditionCheck;
|
|
@Override
|
protected JpaRepository<CustomField, Long> getRepository() {
|
return this.customFieldRepository;
|
}
|
|
// 사용자 정의 필드를 생성한다.
|
@Override
|
@Transactional
|
public CustomField addCustomField(CustomFieldForm customFieldForm) {
|
// 사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다.
|
this.workspaceService.checkUseWorkspace();
|
// 이름 유효성 체크
|
this.verifyName(customFieldForm.getName(), null);
|
// 옵션 값 유효 체크
|
this.verifyOptions(customFieldForm);
|
|
CustomField customField = ConvertUtil.copyProperties(customFieldForm, CustomField.class, "customFieldType");
|
customField.setUse("Y");
|
Workspace workspace = this.workspaceService.getWorkspace(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId());
|
customField.setWorkspace(workspace);
|
customField.setCustomFieldType(CustomFieldType.valueOf(customFieldForm.getCustomFieldType())); // 사용자 정의 필드 유형을 셋팅한다.
|
|
this.customFieldRepository.saveAndFlush(customField);
|
|
this.customFieldValueService.addCustomFieldValues(customField, customFieldForm.getOptions(), null); // 사용자 정의 필드 값 추가
|
|
return customField;
|
}
|
|
// 이름 유효성 체크
|
private void verifyName(String name, Long id) {
|
if (StringUtils.isEmpty(name)) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_NOT_NAME));
|
}
|
|
if (name.length() > 15) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_NAME_MAX_LENGTH_OUT));
|
}
|
|
CustomField customField;
|
Long workspaceId = this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId();
|
|
if (id == null) {
|
customField = this.customFieldRepository.findByNameAndWorkspaceId(name, workspaceId);
|
}
|
else {
|
customField = this.customFieldRepository.findByNameAndWorkspaceIdAndIdNot(name, workspaceId, id);
|
}
|
|
if (customField != null) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_USED_NAME));
|
}
|
}
|
|
// 옵션 값 유효 체크
|
private void verifyOptions(CustomFieldForm customFieldForm) {
|
// 사용자 정의 필드 유형이 텍스트 일때는 옵션 값이 존재하면 안된다.
|
if (CustomFieldType.valueOf(customFieldForm.getCustomFieldType()).equals(CustomFieldType.INPUT)) {
|
if (customFieldForm.getOptions().size() > 0) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_OPTIONS_NOT_USE_INPUT_FIELD));
|
}
|
|
if(customFieldForm.getDefaultValue().length() > 100) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_DEFAULT_VALUE_MAX_LENGTH_OUT));
|
}
|
}
|
|
if (customFieldForm.getOptions().size() > 0) {
|
// 사용자 정의 필드 옵션 값이 null 이거나 공백인 경우를 찾는다.
|
for (String option : customFieldForm.getOptions()) {
|
if (StringUtils.isEmpty(option)) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_OPTIONS_NOT_EMPTY_VALUE));
|
}
|
// 옵션 값 최대 길이 체크
|
if (option.length() > 15) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_OPTION_VALUE_MAX_LENGTH_OUT));
|
}
|
}
|
|
// 사용자 정의 필드 기본 값이 옵션에 존재하지 않을 경우를 찾는다.
|
if (!StringUtils.isEmpty(customFieldForm.getDefaultValue())) {
|
switch (CustomFieldType.valueOf(customFieldForm.getCustomFieldType())) {
|
case SINGLE_SELECT:
|
if (customFieldForm.getDefaultValue().split("#").length > 2) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_OPTIONS_NOT_USE_MULTI_DEFAULT_VALUE));
|
}
|
// 기본 값으로 지정한 값이 옵션에 있는지 확인한다.
|
this.verifyOptionsDefaultValue(customFieldForm);
|
|
break;
|
case MULTI_SELECT:
|
// 기본 값으로 지정한 값이 옵션에 있는지 확인한다.
|
this.verifyOptionsDefaultValue(customFieldForm);
|
break;
|
}
|
}
|
}
|
}
|
|
// 기본 값으로 지정한 값이 옵션에 있는지 확인한다.
|
private void verifyOptionsDefaultValue(CustomFieldForm customFieldForm) {
|
// 중복된 옵션 값 찾기
|
Map<String, Object> optionValueDictionary = new HashMap<>();
|
|
for (String defaultValue : customFieldForm.getDefaultValue().split("#")) {
|
if (!StringUtils.isEmpty(defaultValue)) {
|
if (!customFieldForm.getOptions().contains(defaultValue)) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_OPTIONS_NOT_EXIST_DEFAULT_VALUE));
|
}
|
|
if (MapUtil.getBoolean(optionValueDictionary, defaultValue) == null) {
|
optionValueDictionary.put(defaultValue, true);
|
}
|
else {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_OPTIONS_USED_EXIST_DEFAULT_VALUE));
|
}
|
}
|
}
|
}
|
|
// 사용자 정의 필드 목록을 조회한다.
|
@Override
|
@Transactional(readOnly = true)
|
public List<CustomFieldVo> findCustomField(Map<String, Object> resJsonData,
|
CustomFieldCondition condition, Pageable pageable) {
|
|
condition.setPage(pageable.getPageNumber() * pageable.getPageSize());
|
condition.setPageSize(pageable.getPageSize());
|
condition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId());
|
List<Map<String, Object>> results = this.customFieldMapper.find(condition);
|
Long totalCount = this.customFieldMapper.count(condition);
|
int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1;
|
// 사용자 정의 필드 조회 결과를 CustomFieldVo 로 변환한다.
|
List<CustomFieldVo> customFieldVos = this.makeCustomFieldVos(results);
|
|
resJsonData.put(Constants.REQ_KEY_PAGE_VO, new ResPage(pageable.getPageNumber(), pageable.getPageSize(),
|
totalPage, totalCount));
|
|
resJsonData.put(Constants.RES_KEY_CONTENTS, customFieldVos);
|
|
return customFieldVos;
|
}
|
|
// 사용자 정의 필드 조회 결과를 CustomFieldVo 로 변환한다.
|
private List<CustomFieldVo> makeCustomFieldVos(List<Map<String, Object>> results) {
|
List<CustomFieldVo> customFieldVos = Lists.newArrayList();
|
|
for (Map<String, Object> result : results) {
|
CustomFieldVo customFieldVo = ConvertUtil.convertMapToClass(result, CustomFieldVo.class);
|
CustomField customField = this.getCustomField(customFieldVo.getId());
|
customFieldVo.setCustomFieldValueVos(ConvertUtil.convertObjectsToClasses(customField.getCustomFieldValues(), CustomFieldValueVo.class));
|
customFieldVos.add(customFieldVo);
|
}
|
|
return customFieldVos;
|
}
|
|
|
// 사용자 정의 필드 상세 정보를 조회한다.
|
@Override
|
@Transactional(readOnly = true)
|
public void detailCustomField(Map<String, Object> resJsonData, CustomFieldCondition customFieldCondition) {
|
CustomFieldVo customFieldVo = new CustomFieldVo();
|
|
if (customFieldCondition.getId() != null) {
|
CustomField customField = this.getCustomField(customFieldCondition.getId());
|
customFieldVo = ConvertUtil.copyProperties(customField, CustomFieldVo.class);
|
customFieldVo.setCustomFieldType(customField.getCustomFieldType().toString());
|
|
switch (customFieldCondition.getDeep()) {
|
case "01": // 사용자 정의 필드 옵션 값을 가져온다.
|
customFieldVo.setCustomFieldValueVos(ConvertUtil.convertObjectsToClasses(customField.getCustomFieldValues(), CustomFieldValueVo.class));
|
// 사용자 정의 필드 옵션 값이 이슈에서 사용되고 있는지 확인한 후 플래그 값을 설정한다.
|
List<IssueCustomFieldValue> issueCustomFieldValues = this.issueCustomFieldValueService.findByCustomFieldId(customField);
|
if (issueCustomFieldValues.size() > 0) {
|
customFieldVo.setUseCustomFieldValue(true);
|
}
|
break;
|
}
|
}
|
|
resJsonData.put(Constants.RES_KEY_CONTENTS, customFieldVo);
|
}
|
|
// 사용자 정의 필드를 수정한다.
|
@Override
|
@Transactional
|
public CustomField modifyCustomField(CustomFieldForm customFieldForm) {
|
// 사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다.
|
this.workspaceService.checkUseWorkspace();
|
CustomField customField = this.getCustomField(customFieldForm.getId());
|
CustomFieldType oldCustomFieldType = customField.getCustomFieldType();
|
// 이름 유효성 체크
|
this.verifyName(customFieldForm.getName(), customFieldForm.getId());
|
// 옵션 값 유효 체크
|
this.verifyOptions(customFieldForm);
|
// 사용자 정의 필드 유형이 단일, 다중 선택에서 문자열로 변경될 경우 사용자 정의 필드 값을 초기화한다.
|
this.checkChangeCustomFieldType(customFieldForm, customField);
|
|
ConvertUtil.copyProperties(customFieldForm, customField, "id", "customFieldType");
|
customField.setCustomFieldType(CustomFieldType.valueOf(customFieldForm.getCustomFieldType()));
|
|
this.customFieldRepository.saveAndFlush(customField);
|
this.customFieldValueService.addCustomFieldValues(customField, customFieldForm.getOptions(), oldCustomFieldType); // 사용자 정의 필드 옵션 값 추가
|
|
return customField;
|
}
|
|
// 사용자 정의 필드 유형이 단일, 다중 선택에서 문자열로 변경될 경우 사용자 정의 필드 값을 초기화한다.
|
private void checkChangeCustomFieldType(CustomFieldForm customFieldForm, CustomField customField) {
|
if (!customField.getCustomFieldType().equals(CustomFieldType.INPUT)) {
|
// 단일, 다중 선택에서 문자열 필드로 변경된 경우
|
if (CustomFieldType.valueOf(customFieldForm.getCustomFieldType()).equals(CustomFieldType.INPUT)) {
|
customField.getCustomFieldValues().clear();
|
}
|
}
|
}
|
|
@Override
|
@Transactional(readOnly = true)
|
public CustomField getCustomField(Long id) {
|
if (id == null) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_NOT_EXIST));
|
}
|
|
|
CustomField customField = this.findOne(id);
|
|
if (customField == null) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_NOT_EXIST));
|
}
|
|
return customField;
|
}
|
|
// 사용자 정의 필드를 삭제한다.
|
@Override
|
@Transactional
|
public void removeCustomFields(CustomFieldForm customFieldForm) {
|
// 사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다.
|
this.workspaceService.checkUseWorkspace();
|
|
if (customFieldForm.getRemoveIds().size() < 1) {
|
throw new OwlRuntimeException(
|
this.messageAccessor.getMessage(MsgConstants.CUSTOM_FIELD_REMOVE_NOT_SELECT));
|
}
|
|
for (Long projectId : customFieldForm.getRemoveIds()) {
|
this.removeCustomFields(projectId);
|
}
|
|
// this.customFieldRepository.flush();
|
}
|
|
private void removeCustomFields(Long customFieldId) {
|
CustomField customField = this.getCustomField(customFieldId);
|
customField.setUse(UseType.N.toString());
|
this.customFieldRepository.saveAndFlush(customField);
|
// this.customFieldRepository.delete(customField);
|
}
|
|
// 이슈 엑셀 import 에서 사용한다.
|
@Override
|
@Transactional(readOnly = true)
|
public CustomField findByName(String name) {
|
return this.customFieldRepository.findByNameAndWorkspaceId(name, this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId());
|
}
|
|
// 사용자 정의 필드 목록을 엑셀로 다운로드 한다.
|
@Override
|
@Transactional
|
public ModelAndView downloadExcel(HttpServletRequest request, Model model) {
|
// 사용 공간에서 로그인한 사용자가 비활성인지 확인하고 비활성일 경우 엑셀 다운로드를 금지한다.
|
ModelAndView modelAndView = this.workspaceService.checkUseExcelDownload(model);
|
if (modelAndView != null) {
|
return modelAndView;
|
}
|
|
Map<String, Object> conditions = new HashMap<>();
|
// 엑셀 다운로드에 필요한 검색 조건 정보를 추출하고 검색 조건 추출에 오류가 발생하면 경고를 표시해준다.
|
modelAndView = this.excelConditionCheck.checkCondition(conditions, request, model);
|
if (modelAndView != null) {
|
return modelAndView;
|
}
|
|
CustomFieldCondition customFieldCondition = CustomFieldCondition.make(conditions);
|
customFieldCondition.setWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId());
|
List<Map<String, Object>> results = this.customFieldMapper.find(customFieldCondition);
|
|
for (Map<String, Object> result : results) {
|
String customFieldType = MapUtil.getString(result, "customFieldType");
|
String customFieldTypeName = "";
|
|
if (customFieldType != null) {
|
switch(customFieldType) {
|
case "INPUT" :
|
customFieldTypeName = this.messageAccessor.message("common.stringField"); // 문자열 필드
|
break;
|
case "SINGLE_SELECT" :
|
customFieldTypeName = this.messageAccessor.message("common.singleSelectionField"); // 단일 선택 필드
|
break;
|
case "MULTI_SELECT" :
|
customFieldTypeName = this.messageAccessor.message("common.multipleSelectionField"); // 다중 선택 필드
|
break;
|
}
|
}
|
|
result.put("customFieldTypeName", customFieldTypeName);
|
}
|
|
ExportExcelVo excelInfo = new ExportExcelVo();
|
excelInfo.setFileName(this.messageAccessor.message("common.customFieldList")); // 사용자 정의 필드 목록
|
excelInfo.addAttrInfos(new ExportExcelAttrVo("name", this.messageAccessor.message("common.customField"), 15, ExportExcelAttrVo.ALIGN_LEFT)); // 사용자 정의 필드
|
excelInfo.addAttrInfos(new ExportExcelAttrVo("customFieldTypeName", this.messageAccessor.message("common.fieldType"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 필드 유형
|
// 엑셀에 넣을 데이터
|
excelInfo.setDatas(results);
|
model.addAttribute(Constants.EXCEL, excelInfo);
|
return new ModelAndView(this.excelView);
|
}
|
|
// 업무 공간에 있는 모든 사용자 정의 필드을 조회한다. 이슈 엑셀 import 에서 사용
|
@Override
|
@Transactional(readOnly = true)
|
public List<CustomField> findByWorkspaceId() {
|
return this.customFieldRepository.findByWorkspaceId(this.userService.getUser(this.webAppUtil.getLoginId()).getLastWorkspaceId());
|
}
|
}
|