OWL ITS + 탐지시스템(인터넷 진흥원)
이민희
2021-11-15 dc873bdc1e57945d6cb6eadd41ef38cc2a4b35d3
담당자 -> 담당부서 변경
* db날리고 실행
17개 파일 변경됨
439 ■■■■ 파일 변경됨
src/main/java/kr/wisestone/owl/domain/Department.java 19 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/domain/ProjectRoleUser.java 18 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/mapper/IssueUserMapper.java 14 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/repository/ProjectRoleUserRepository.java 2 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/IssueService.java 4 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/IssueUserService.java 9 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/ProjectRoleUserService.java 4 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java 195 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/IssueUserServiceImpl.java 77 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/ProjectRoleServiceImpl.java 17 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/ProjectRoleUserServiceImpl.java 7 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/condition/IssueCondition.java 13 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/controller/IssueUserController.java 3 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/form/IssueForm.java 14 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/migration/V1_1__Initial_Setup.sql 6 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/mybatis/query-template/issueUser-template.xml 36 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/WEB-INF/i18n/code_ko_KR.properties 1 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/domain/Department.java
@@ -1,10 +1,9 @@
package kr.wisestone.owl.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
@Entity
public class Department extends BaseEntity implements Serializable {
@@ -16,6 +15,9 @@
    private Long id;
    private String departmentName;
    private String departmentDescription;
    @OneToMany(mappedBy = "department", cascade = {CascadeType.ALL}, orphanRemoval = true)
    private Set<ProjectRoleUser> projectRoleDepartments = new HashSet<>();
    public Department() {
    }
@@ -43,4 +45,13 @@
    public void setDepartmentDescription(String departmentDescription) {
        this.departmentDescription = departmentDescription;
    }
    /*public void addProjectRole(ProjectRole projectRole) {
        if (this.projectRoleDepartments == null) {
            this.projectRoleDepartments = new HashSet<>();
        }
        ProjectRoleUser projectRoleUser = new ProjectRoleUser(projectRole, this);
        this.projectRoleDepartments.add(projectRoleUser);
    }*/
}
src/main/java/kr/wisestone/owl/domain/ProjectRoleUser.java
@@ -22,6 +22,10 @@
    @JoinColumn(name="user_id")
    private User user;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="department_id")
    private Department department;
    public ProjectRoleUser() {
    }
@@ -29,6 +33,12 @@
        this.projectRole = projectRole;
        this.user = user;
    }
    //부서로 변경
    /*public ProjectRoleUser(ProjectRole projectRole, Department department) {
        this.projectRole = projectRole;
        this.department = department;
    }*/
    public Long getId() {
        return id;
@@ -53,4 +63,12 @@
    public void setUser(User user) {
        this.user = user;
    }
    public Department getDepartment() {
        return department;
    }
    public void setDepartment(Department department) {
        this.department = department;
    }
}
src/main/java/kr/wisestone/owl/mapper/IssueUserMapper.java
@@ -10,12 +10,22 @@
 */
@Repository
public interface IssueUserMapper {
    void insertIssueUser(List<Map<String, Long>> issueRoleUserMaps);
    //담당자
    void deleteIssueUserByIssueIdAndMultiUserId(Map<String, Object> removeIssueAssigneeMap);
    void deleteIssueUserByUserIdAndMultiIssueId(Map<String, Object> removeIssueAssigneeMap);
    List<Map<String, Object>> findByUserIdAndProjectId(Map<String, Object> issueUserMap);
    //담당부서
    void deleteIssueUserByIssueIdAndMultiDepartmentId(Map<String, Object> removeIssueAssigneeMap);
    void deleteIssueUserByDepartmentIdAndMultiIssueId(Map<String, Object> removeIssueAssigneeMap);
    List<Map<String, Object>> findByDepartmentIdAndProjectId(Map<String, Object> issueUserMap);
}
src/main/java/kr/wisestone/owl/repository/ProjectRoleUserRepository.java
@@ -11,4 +11,6 @@
    ProjectRoleUser findByProjectRoleIdAndUserId(@Param("projectRoleId") Long projectRoleId, @Param("userId") Long userId);
    ProjectRoleUser findByProjectRoleIdAndDepartmentId(@Param("projectRoleId") Long projectRoleId, @Param("departmentId") Long departmentId);
}
src/main/java/kr/wisestone/owl/service/IssueService.java
@@ -51,7 +51,9 @@
    void modifyMultiIssueStatus(IssueForm issueForm);
    void modifyIssueUser(IssueForm issueForm);
    //void modifyIssueUser(IssueForm issueForm);
    void modifyIssueDepartment(IssueForm issueForm);
    ModelAndView downloadExcelTemplate(HttpServletRequest request, Model model);
src/main/java/kr/wisestone/owl/service/IssueUserService.java
@@ -10,11 +10,20 @@
import java.util.Map;
public interface IssueUserService extends AbstractService<IssueUser, Long, JpaRepository<IssueUser, Long>>{
    //담당자
    void modifyIssueUser(Issue issue, Workspace workspace, List<Long> userIds);
    void insertIssueUser(List<Map<String, Long>> issueAssigneeMaps);
    void removeIssueUser(Long projectId, List<Long> excludeUserIds);
    //담당부서
    void modifyIssueDepartment(Issue issue, Workspace workspace, List<Long> departmentIds);
    void insertIssueDepartment(List<Map<String, Long>> issueAssigneeMaps);
    void removeIssueDepartment(Long projectId, List<Long> excludeUserIds);
    List<IssueUser> find(Issue issue);
}
src/main/java/kr/wisestone/owl/service/ProjectRoleUserService.java
@@ -12,7 +12,9 @@
public interface ProjectRoleUserService extends AbstractService<ProjectRoleUser, Long, JpaRepository<ProjectRoleUser, Long>>{
    List<ProjectRoleUser> findByProjectRoleId(Long projectRoleId);
    ProjectRoleUser findByProjectRoleIdAndUserId(Long projectRoleId, Long userId);
    ProjectRoleUser findByProjectRoleIdAndUserId(Long projectRoleId, Long userId); //담당자
    ProjectRoleUser findByProjectRoleIdAndDepartmentId(Long projectRoleId, Long departmentId); //담당부서
    void withDrawWorkspaceManagerModifyProjectRole(Workspace workspace, User user);
src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -187,7 +187,9 @@
        issue.setReverseIndex(issue.getId() * -1);  //  쿼리 속도 개선을 위해 리버스 인덱스 생성
        //  담당자 지정
        this.issueUserService.modifyIssueUser(issue, project.getWorkspace(), issueForm.getUserIds());
        //this.issueUserService.modifyIssueUser(issue, project.getWorkspace(), issueForm.getUserIds());
        //  담당부서 지정
        this.issueUserService.modifyIssueDepartment(issue, project.getWorkspace(), issueForm.getDepartmentIds());
        //  multipartFile 을 file Map List 객체로 변경한다.
        List<Map<String, Object>> convertFileMaps = this.convertMultipartFileToFile(multipartFiles);
@@ -242,13 +244,14 @@
        issueMap.put("issueTypeName", issue.getIssueType().getName());
        issueMap.put("issueStatusName", issue.getIssueStatus().getName());
        //  담당자
        //  담당부서
        StringBuilder assigneeBuilder = new StringBuilder();
        for (IssueUser issueUser : issue.getIssueUsers()) {
            assigneeBuilder.append(issueUser.getUser().getName());
            assigneeBuilder.append("(");
            //assigneeBuilder.append(issueUser.getUser().getName());
            assigneeBuilder.append(issueUser.getDepartment().getDepartmentName());
            /*assigneeBuilder.append("(");
            assigneeBuilder.append(CommonUtil.decryptAES128(issueUser.getUser().getAccount()));
            assigneeBuilder.append(")");
            assigneeBuilder.append(")");*/
            assigneeBuilder.append("\n");
        }
@@ -514,7 +517,8 @@
        }
        //  이슈 사용자 정보 추가
        this.setIssueUserList(issueVos, issueCondition);
        //this.setIssueUserList(issueVos, issueCondition);
        this.setIssueDepartmentList(issueVos, issueCondition);
        //  등록자 정보 추가
        this.setRegister(issueVos);  //  담당자 정보 셋팅
@@ -656,8 +660,8 @@
        return true;
    }
    //  이슈 담당자 정보를 셋팅한다.
    private void setIssueUserList(List<IssueVo> issueVos, IssueCondition issueCondition) {
    //  이슈 담당자 정보를 셋팅한다. => 담당부서
    private void setIssueDepartmentList(List<IssueVo> issueVos, IssueCondition issueCondition) {
        if (issueVos.size() < 1) {
            return;
        }
@@ -665,26 +669,30 @@
        List<Map<String, Object>> issueUsers = this.issueMapper.findIssueUser(issueCondition);
        Map<String, Object> issueConverterUsers = new HashMap<>();
        //  이슈에 해당하는 이슈 담당자 정보 셋팅
        //  이슈에 해당하는 이슈 담당부서 정보 셋팅
        for (Map<String, Object> issueUser : issueUsers) {
            String issueId = MapUtil.getString(issueUser, "issueId");
            if (MapUtil.getObject(issueConverterUsers, issueId) != null) {
                List<UserVo> users = (List) MapUtil.getObject(issueConverterUsers, issueId);
                users.add(new UserVo(MapUtil.getLong(issueUser, "id"), MapUtil.getString(issueUser, "name"), CommonUtil.decryptAES128(MapUtil.getString(issueUser, "account")), MapUtil.getString(issueUser, "profile")));
                List<DepartmentVo> departments = (List) MapUtil.getObject(issueConverterUsers, issueId);
                departments.add(new DepartmentVo(MapUtil.getLong(issueUser, "id"), MapUtil.getString(issueUser, "departmentName"), MapUtil.getString(issueUser, "departmentDescription")));
                //List<UserVo> users = (List) MapUtil.getObject(issueConverterUsers, issueId);
                //users.add(new UserVo(MapUtil.getLong(issueUser, "id"), MapUtil.getString(issueUser, "name"), CommonUtil.decryptAES128(MapUtil.getString(issueUser, "account")), MapUtil.getString(issueUser, "profile")));
            } else {
                List<UserVo> users = Lists.newArrayList(new UserVo(MapUtil.getLong(issueUser, "id"), MapUtil.getString(issueUser, "name"), CommonUtil.decryptAES128(MapUtil.getString(issueUser, "account")),
                List<DepartmentVo> departments = Lists.newArrayList(new DepartmentVo(MapUtil.getLong(issueUser, "id"), MapUtil.getString(issueUser, "departmentName"), MapUtil.getString(issueUser, "departmentDescription")));
                issueConverterUsers.put(issueId, departments);
                /*List<UserVo> users = Lists.newArrayList(new UserVo(MapUtil.getLong(issueUser, "id"), MapUtil.getString(issueUser, "name"), CommonUtil.decryptAES128(MapUtil.getString(issueUser, "account")),
                        MapUtil.getString(issueUser, "profile")));
                issueConverterUsers.put(issueId, users);
                issueConverterUsers.put(issueId, users);*/
            }
        }
        //  이슈Vo에 담당자 정보를 셋팅
        //  이슈Vo에 담당부서 정보를 셋팅
        for (IssueVo issueVo : issueVos) {
            if (MapUtil.getObject(issueConverterUsers, String.valueOf(issueVo.getId())) != null) {
                List<UserVo> userVos = (List) MapUtil.getObject(issueConverterUsers, String.valueOf(issueVo.getId()));
                List<DepartmentVo> departmentVos = (List) MapUtil.getObject(issueConverterUsers, String.valueOf(issueVo.getId()));
                issueVo.setUserVos(userVos);
                issueVo.setDepartmentVos(departmentVos);
            }
            //  이슈 수정 권한을 갖고 있는지 확인
@@ -705,7 +713,7 @@
            issueVo = ConvertUtil.copyProperties(issue, IssueVo.class);
            switch (issueCondition.getDeep()) {
                case "01": //  프로젝트, 이슈 유형, 이슈 상태,  우선순위, 중요도, 담당자, 첨부파일, 사용자 정의 필드 정보를 셋팅한다.
                case "01": //  프로젝트, 이슈 유형, 이슈 상태,  우선순위, 중요도, 담당부서, 첨부파일, 사용자 정의 필드 정보를 셋팅한다.
                    issueVo.setProjectVo(ConvertUtil.copyProperties(issue.getProject(), ProjectVo.class));
                    issueVo.setIssueTypeVo(ConvertUtil.copyProperties(issue.getIssueType(), IssueTypeVo.class));
                    issueVo.setIssueStatusVo(ConvertUtil.copyProperties(issue.getIssueStatus(), IssueStatusVo.class));
@@ -713,7 +721,8 @@
                    issueVo.setSeverityVo(ConvertUtil.copyProperties(issue.getSeverity(), SeverityVo.class));
                    this.setRegister(issue, issueVo);   //  등록자 정보 셋팅
                    this.setIssueUser(issue, issueVo);  //  담당자 정보 셋팅
                    //this.setIssueUser(issue, issueVo);  //  담당자 정보 셋팅
                    this.setIssueDepartment(issue, issueVo);  //  담당부서 정보 셋팅
                    this.setAttachedFiles(issue, issueVo);  //  첨부 파일 정보 셋팅
                    this.setIssueCustomFields(issue, issueVo);  //  사용자 정의 필드 값 정보 셋팅
                    this.setRelationIssue(issue, issueVo);        //연관 일감 셋팅
@@ -743,7 +752,7 @@
        issueVo.setPriorityVo(ConvertUtil.copyProperties(issue.getPriority(), PriorityVo.class));
        issueVo.setSeverityVo(ConvertUtil.copyProperties(issue.getSeverity(), SeverityVo.class));
        this.setRegister(issue, issueVo);   //  등록자 정보 셋팅
        this.setIssueUser(issue, issueVo);  //  담당자 정보 셋팅
        //this.setIssueUser(issue, issueVo);  //  담당자 정보 셋팅
        this.setIssueDepartment(issue, issueVo);  //  담당부서 정보 셋팅
        this.setAttachedFiles(issue, issueVo);  //  첨부 파일 정보 셋팅
        this.setIssueCustomFields(issue, issueVo);  //  사용자 정의 필드 값 정보 셋팅
@@ -796,7 +805,7 @@
    }
    //  이슈 담당자 정보를 셋팅한다.
    private void setIssueUser(Issue issue, IssueVo issueVo) {
    /*private void setIssueUser(Issue issue, IssueVo issueVo) {
        List<UserVo> userVos = Lists.newArrayList();
        for (IssueUser issueUser : issue.getIssueUsers()) {
@@ -829,7 +838,7 @@
        }
        issueVo.setUserVos(userVos);
    }
    }*/
    //  이슈 담당부서 정보를 셋팅한다.
    private void setIssueDepartment(Issue issue, IssueVo issueVo) {
@@ -888,7 +897,7 @@
        //  사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다.
        this.workspaceService.checkUseWorkspace();
        //  이슈 수정 권한 체크
        this.verifyIssueModifyPermission(issueForm.getId());
        //this.verifyIssueModifyPermission(issueForm.getId());
        //  프로젝트 유효성 체크
        Project project = this.projectService.getProject(issueForm.getProjectId());
        //  이슈 상태 유효성 체크
@@ -904,7 +913,7 @@
        //  날짜 유효성 체크
        this.checkStartCompleteDate(issueForm.getStartDate(), issueForm.getCompleteDate());
        //  담당자 유효성 체크
        //  담당자 유효성 체크 => 담당부서로 변경
        this.verifyIssueAssignee(project, issueForm);
        Issue issue = this.getIssue(issueForm.getId());
@@ -933,8 +942,9 @@
        issue.setCompleteDate(issueForm.getCompleteDate());
        this.issueRepository.saveAndFlush(issue);
        //  담당자 지정
        this.issueUserService.modifyIssueUser(issue, project.getWorkspace(), issueForm.getUserIds());
        //  담당부서 지정
        //this.issueUserService.modifyIssueUser(issue, project.getWorkspace(), issueForm.getUserIds());
        this.issueUserService.modifyIssueDepartment(issue, project.getWorkspace(), issueForm.getDepartmentIds());
        //  multipartFile 을 file Map List 객체로 변경한다.
        List<Map<String, Object>> convertFileMaps = this.convertMultipartFileToFile(multipartFiles);
@@ -1007,7 +1017,36 @@
        return false;
    }
    //  이슈 담당자로 지정될 사용자가 해당 프로젝트에 참여 하고 있는 사용자 인지 확인
    //  이슈 담당부서로 지정될 부서가 해당 프로젝트에 참여 하고 있는 부서인지 확인
    private void verifyIssueAssignee(Project project, IssueForm issueForm) {
        if (issueForm.getDepartmentIds().size() > 0) {
            List<Long> trustDepartmentIds = Lists.newArrayList(); //  참여 확인된 부서
            for (Long departmentId : issueForm.getDepartmentIds()) {
                boolean includeProject = false;
                for (ProjectRole projectRole : project.getProjectRoles()) {
                    ProjectRoleUser projectRoleUser = this.projectRoleUserService.findByProjectRoleIdAndDepartmentId(projectRole.getId(), departmentId);
                    if (projectRoleUser != null) {
                        includeProject = true;
                        trustDepartmentIds.add(departmentId);
                        break;
                    }
                }
                //  데이터 보정 작업 - 프로젝트에서 제외된 사용자는 담당자에서 제외 될 수 있도록 처리
                /*if (!includeProject) {
                    throw new OwlRuntimeException(
                            this.messageAccessor.getMessage(MsgConstants.PROJECT_NOT_INCLUDE_USER));
                }*/
            }
            //  참여 확인된 부서로 담당부서 변경
            issueForm.setDepartmentIds(trustDepartmentIds);
        }
    }
    /*//  이슈 담당자로 지정될 사용자가 해당 프로젝트에 참여 하고 있는 사용자 인지 확인
    private void verifyIssueAssignee(Project project, IssueForm issueForm) {
        if (issueForm.getUserIds().size() > 0) {
            List<Long> trustUserIds = Lists.newArrayList(); //  참여 확인된 사용자
@@ -1026,17 +1065,17 @@
                }
                //  데이터 보정 작업 - 프로젝트에서 제외된 사용자는 담당자에서 제외 될 수 있도록 처리
                /*if (!includeProject) {
                *//*if (!includeProject) {
                    throw new OwlRuntimeException(
                            this.messageAccessor.getMessage(MsgConstants.PROJECT_NOT_INCLUDE_USER));
                }*/
                }*//*
            }
            //  참여 확인된 사용자로 담당자 변경
            issueForm.setUserIds(trustUserIds);
        }
    }
    }*/
    //  이슈 수정 권한 체크
    /*//  이슈 수정 권한 체크
    private void verifyIssueModifyPermission(Long issueId) {
        Issue issue = this.getIssue(issueId);
@@ -1057,7 +1096,7 @@
        }
        return userVos;
    }
    }*/
    //  이슈 수정 권한을 갖고 있는지 확인
    private boolean checkHasPermission(IssueVo issueVo, List<UserVo> issueUserVos) {
@@ -1069,8 +1108,8 @@
        hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.PROJECT_MANAGER, issueVo, null);
        //   이슈 등록자일 경우 수정 권한을 갖는다.
        hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.REGISTER, issueVo, null);
        //  이슈 담당자일 경우 수정 권한을 갖는다.
        hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.ASSIGNEE, issueVo, issueUserVos);
        //  이슈 담당자일 경우 수정 권한을 갖는다. => 담당부서로 수정 - 체크
        //hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.ASSIGNEE, issueVo, issueUserVos);
        //  담당자가 없으면 모든 사용자가 수정 권한을 갖는다.
        return hasPermission;
@@ -1102,13 +1141,13 @@
                        break;
                    }
                    //   이슈 담당자 여부 확인
                    for (UserVo issueUserVo : issueUserVos) {
                    //   이슈 담당자 여부 확인 => 담당부서로 수정 - 체크
                    /*for (UserVo issueUserVo : issueUserVos) {
                        if (issueUserVo.getId().equals(this.webAppUtil.getLoginId())) {
                            hasPermission = true;
                            break;
                        }
                    }
                    }*/
                    break;
            }
@@ -1126,7 +1165,7 @@
        //  변경 이력 정보 추출
        StringBuilder detectIssueChange = new StringBuilder();
        //  이슈 수정 권한 체크
        this.verifyIssueModifyPermission(issueForm.getId());
        //this.verifyIssueModifyPermission(issueForm.getId());
        Issue issue = this.getIssue(issueForm.getId());
        IssueStatus issueStatus = this.issueStatusService.getIssueStatus(issueForm.getIssueStatusId());
@@ -1164,7 +1203,7 @@
    }
    //  이슈 담당자 변경
    @Override
    /*@Override
    @Transactional
    public void modifyIssueUser(IssueForm issueForm) {
        //  사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다.
@@ -1179,7 +1218,43 @@
        //  변경 이력 정보 추출
        this.issueHistoryService.detectIssueManager(issue, issueForm, detectIssueChange);
        this.issueUserService.modifyIssueUser(issue, issue.getProject().getWorkspace(), issueForm.getUserIds());
        this.issueUserService.modifyIssueUser(issue, issue.getProject().getWorkspace(), issueForm.getDepartmentIds()); //getUserIds -> getDepartmentIds
        this.issueRepository.saveAndFlush(issue);
        //  이슈 이력 등록
        if (!StringUtils.isEmpty(detectIssueChange.toString())) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("<ul class=\"activity-list\">");
            stringBuilder.append(detectIssueChange.toString());
            stringBuilder.append("</ul>");
            this.issueHistoryService.addIssueHistory(issue, IssueHistoryType.MODIFY, stringBuilder.toString());
        }
        //  이슈 버전 생성
        this.issueVersionService.addIssueVersion(issue);
        //  사용자 시스템 기능 사용 정보 수집
        log.info(ElasticSearchUtil.makeUserActiveHistoryMessage(this.webAppUtil.getLoginUser(), ElasticSearchConstants.ISSUE_USER_CHANGE));
    }*/
    @Override
    @Transactional
    public void modifyIssueDepartment(IssueForm issueForm) {
        //  사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다.
        this.workspaceService.checkUseWorkspace();
        //  변경 이력 정보 추출
        StringBuilder detectIssueChange = new StringBuilder();
        //  이슈 수정 권한 체크
        //this.verifyIssueModifyPermission(issueForm.getId());
        Issue issue = this.getIssue(issueForm.getId());
        issue.setProject(this.projectService.getProject(issueForm.getProjectId()));
        //  변경 이력 정보 추출
        this.issueHistoryService.detectIssueManager(issue, issueForm, detectIssueChange);
        //this.issueUserService.modifyIssueUser(issue, issue.getProject().getWorkspace(), issueForm.getUserIds());
        this.issueUserService.modifyIssueDepartment(issue, issue.getProject().getWorkspace(), issueForm.getDepartmentIds());
        this.issueRepository.saveAndFlush(issue);
        //  이슈 이력 등록
@@ -1229,7 +1304,7 @@
    private Issue issueRemoves(Long issueId) {
        Issue issue = this.getIssue(issueId);
        //  이슈 수정 권한을 갖고 있는지 확인
        this.verifyIssueModifyPermission(issueId);
        //this.verifyIssueModifyPermission(issueId);
        //  이슈 첨부 파일을 삭제한다.
        if (issue.getAttachedFiles().size() > 0) {
@@ -1366,7 +1441,7 @@
        excelInfo.addAttrInfos(new ExportExcelAttrVo("title", this.messageAccessor.message("common.issueTitle"), 40, ExportExcelAttrVo.ALIGN_LEFT)); // 이슈 제목
        excelInfo.addAttrInfos(new ExportExcelAttrVo("description", this.messageAccessor.message("common.content"), 60, ExportExcelAttrVo.ALIGN_LEFT)); // 내용
        excelInfo.addAttrInfos(new ExportExcelAttrVo("issueTypeName", this.messageAccessor.message("common.issueType"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 이슈 타입
        excelInfo.addAttrInfos(new ExportExcelAttrVo("assignees", this.messageAccessor.message("common.assignee"), 20, ExportExcelAttrVo.ALIGN_CENTER)); // 담당자
        excelInfo.addAttrInfos(new ExportExcelAttrVo("department", this.messageAccessor.message("common.department"), 20, ExportExcelAttrVo.ALIGN_CENTER)); // 담당부서
        excelInfo.addAttrInfos(new ExportExcelAttrVo("priorityName", this.messageAccessor.message("common.priority"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 우선순위
        excelInfo.addAttrInfos(new ExportExcelAttrVo("severityName", this.messageAccessor.message("common.importance"), 6, ExportExcelAttrVo.ALIGN_CENTER)); // 중요도
        excelInfo.addAttrInfos(new ExportExcelAttrVo("register", this.messageAccessor.message("common.register"), 20, ExportExcelAttrVo.ALIGN_CENTER)); // 등록자
@@ -1542,7 +1617,7 @@
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("common.issueType"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 이슈 타입
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("common.priority"), 5, ExportExcelAttrVo.ALIGN_CENTER)); // 우선순위
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("common.importance"), 5, ExportExcelAttrVo.ALIGN_CENTER)); // 중요도
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("common.assignee"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 담당자
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("common.department"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 담당부서
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("common.startDate"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 시작일
        excelInfo.addAttrInfos(new ExportExcelAttrVo("id", this.messageAccessor.message("common.endDate"), 10, ExportExcelAttrVo.ALIGN_CENTER)); // 종료일
        //  프로젝트에 연결된 사용자 정의 필드 정보를 추출하여 엑셀 download 템플릿을 만든다.
@@ -1714,10 +1789,11 @@
        List<Map<String, Long>> issueAssigneeMaps = Lists.newArrayList();
        for (IssueForm issueForm : issueForms) {
            for (Long userId : issueForm.getUserIds()) {
            for (Long departmentId : issueForm.getDepartmentIds()) {
                Map<String, Long> issueAssigneeMap = new HashMap<>();
                issueAssigneeMap.put("issueId", issueForm.getId());
                issueAssigneeMap.put("userId", userId);
                //issueAssigneeMap.put("userId", userId);
                issueAssigneeMap.put("departmentId", departmentId);
                issueAssigneeMap.put("workspaceId", workspace.getId());
                issueAssigneeMap.put("registerId", this.webAppUtil.getLoginId());
                issueAssigneeMaps.add(issueAssigneeMap);
@@ -1880,7 +1956,7 @@
                    this.setIssueFormSeverity(cell, severityMaps, issueForm, rowIndex);
                    break;
                case 6:
                    //  담당자를 IssueForm 에 저장한다.
                    //  담당부서를 IssueForm 에 저장한다.
                    this.setIssueFormAssignee(cell, userMaps, issueForm, project);
                    break;
                case 7:
@@ -2021,21 +2097,21 @@
        issueForm.setSeverityId(severity.getId());
    }
    //  담당자를 IssueForm 에 저장한다.
    //  담당부서를 IssueForm 에 저장한다.
    private void setIssueFormAssignee(Cell cell, Map<String, Object> userMaps, IssueForm issueForm, Project project) {
        if (cell != null) {
            String[] splitAssignee = CommonUtil.convertExcelStringToCell(cell).split("#");
            Map<String, Object> userMap = (Map<String, Object>) MapUtil.getObject(userMaps, project.getProjectKey());
            List<Long> userIds = Lists.newArrayList();
            List<Long> departmentIds = Lists.newArrayList();
            for (String account : splitAssignee) {
                if (MapUtil.getLong(userMap, account) != null) {
                    userIds.add(MapUtil.getLong(userMap, account));
                    departmentIds.add(MapUtil.getLong(userMap, account));
                }
            }
            issueForm.setUserIds(userIds);
            issueForm.setDepartmentIds(departmentIds);
        }
    }
@@ -2298,17 +2374,24 @@
            taskUserSave.put(taskId.toString(), Lists.newArrayList());
        }
        List<Map<String, Object>> taskUsers = Lists.newArrayList();
        List<Map<String, Object>> taskDepartments = Lists.newArrayList();
        //  task 가 하나도 없을 경우에는 조회를 하지 않는다.
        if (!taskCondition.getIssueIds().isEmpty()) {
            taskUsers = this.issueMapper.getAllTaskUser(taskCondition);
            //taskUsers = this.issueMapper.getAllTaskUser(taskCondition);
            taskDepartments = this.issueMapper.getAllTaskUser(taskCondition);
        }
        //  task_id 에 매칭되는 담당자 정보를 준비한다.
        for (Map<String, Object> taskUser : taskUsers) {
        /*for (Map<String, Object> taskUser : taskUsers) {
            Long taskId = MapUtil.getLong(taskUser, "taskId");
            List<UserVo> userVos = (List<UserVo>)taskUserSave.get(taskId.toString());
            userVos.add(ConvertUtil.convertMapToClass(taskUser, UserVo.class));
        }*/
        for (Map<String, Object> taskDepartment : taskDepartments) {
            Long taskId = MapUtil.getLong(taskDepartment, "taskId");
            List<DepartmentVo> departmentVos = (List<DepartmentVo>)taskUserSave.get(taskId.toString());
            departmentVos.add(ConvertUtil.convertMapToClass(taskDepartment, DepartmentVo.class));
        }
        for (Map<String, Object> result : results) {
@@ -2333,8 +2416,12 @@
            }
            //  담당자 셋팅
            List<UserVo> userVos =  (List<UserVo>)taskUserSave.get(taskVo.getId().toString());
            taskVo.setUserVos(userVos);
            //List<UserVo> userVos =  (List<UserVo>)taskUserSave.get(taskVo.getId().toString());
            //taskVo.setUserVos(userVos);
            //  담당부서 세팅
            List<DepartmentVo> departmentVos = (List<DepartmentVo>)taskUserSave.get(taskVo.getId().toString());
            taskVo.setDepartmentVos(departmentVos);
            List<IssueVo> taskVos = (List<IssueVo>)tasks.get(MapUtil.getString(result, "workflowStatusId"));
            taskVos.add(taskVo);
src/main/java/kr/wisestone/owl/service/impl/IssueUserServiceImpl.java
@@ -75,7 +75,84 @@
        }
    }
    //  이슈 담당부서를 변경한다.
    @Override
    @Transactional
    public void modifyIssueDepartment(Issue issue, Workspace workspace, List<Long> departmentIds) {
        List<Long> oldDepartmentIds = Lists.newArrayList();
        //  이전 담당 부서
        for (IssueUser issueUser : issue.getIssueUsers()) {
            oldDepartmentIds.add(issueUser.getDepartment().getId());
        }
        List<Long> newDepartmentIds = CommonUtil.searchChangeList(oldDepartmentIds, departmentIds); //  추가해야할 부서를 찾는다.
        List<Long> removeDepartmentIds = CommonUtil.searchChangeList(departmentIds, oldDepartmentIds); //  삭제해야할 부서를 찾는다.
        if (removeDepartmentIds.size() > 0) {
            Map<String, Object> removeIssueAssigneeMap = new HashMap<>();
            removeIssueAssigneeMap.put("issueId", issue.getId());
            removeIssueAssigneeMap.put("departmentIds", removeDepartmentIds);
            //  담당부서 삭제
            this.issueUserMapper.deleteIssueUserByIssueIdAndMultiDepartmentId(removeIssueAssigneeMap);
        }
        if (newDepartmentIds.size() > 0) {
            List<Map<String, Long>> addIssueAssigneeMaps = Lists.newArrayList();
            for (Long departmentId : newDepartmentIds) {
                Map<String, Long> issueAssigneeMap = new HashMap<>();
                issueAssigneeMap.put("departmentId", departmentId); //담당부서
                issueAssigneeMap.put("issueId", issue.getId());
                issueAssigneeMap.put("workspaceId", workspace.getId());
                issueAssigneeMap.put("registerId", this.webAppUtil.getLoginId());
                addIssueAssigneeMaps.add(issueAssigneeMap);
            }
            //  담당부서 추가
            this.issueUserMapper.insertIssueUser(addIssueAssigneeMaps);
        }
    }
    @Override
    @Transactional
    public void insertIssueDepartment(List<Map<String, Long>> issueAssigneeMaps) {
        //  이슈 담당부서 벌크 등록
        this.issueUserMapper.insertIssueUser(issueAssigneeMaps);
    }
    //  이슈 담당부서에서 제외한다.
    @Override
    @Transactional
    public void removeIssueDepartment(Long projectId, List<Long> excludeDepartmentIds) {
        for (Long departmentId : excludeDepartmentIds) {
            Map<String, Object> issueUserMap = new HashMap<>();
            issueUserMap.put("departmentId", departmentId);
            issueUserMap.put("projectId", projectId);
            List<Map<String, Object>> results = this.issueUserMapper.findByDepartmentIdAndProjectId(issueUserMap);
            if (results.size() > 0) {
                List<Long> issueIds = Lists.newArrayList();
                for (Map<String, Object> result : results) {
                    Long id = MapUtil.getLong(result, "id");
                    if (id != null) {
                        issueIds.add(id);
                    }
                }
                if (issueIds.size() > 0) {
                    Map<String, Object> removeIssueAssigneeMap = new HashMap<>();
                    removeIssueAssigneeMap.put("departmentId", departmentId);
                    removeIssueAssigneeMap.put("issueIds", issueIds);
                    this.issueUserMapper.deleteIssueUserByDepartmentIdAndMultiIssueId(removeIssueAssigneeMap);
                }
            }
        }
    }
    //  이슈 담당자 찾기
    @Override
src/main/java/kr/wisestone/owl/service/impl/ProjectRoleServiceImpl.java
@@ -64,6 +64,23 @@
        }
    }
    /*// 프로젝트 역할과 부서 연결
    private void projectRoleAssociatedDepartment(List<Department> departments, ProjectRole projectRole) {
        for (Department department : departments) {
            this.addDefaultProjectRoleAssociatedDepartment(projectRole, department);
        }
    }
    //  해당 역할과 부서를 연결시킨다.
    private void addDefaultProjectRoleAssociatedDepartment(ProjectRole projectRole, Department department) {
        ProjectRoleUser projectRoleDepartment = this.projectRoleUserService.findByProjectRoleIdAndDepartmentId(projectRole.getId(), department.getId());
        if (projectRoleDepartment == null) {
            //  프로젝트 관리자 - 기본 프로젝트 역할에 추가.
            department.addProjectRole(projectRole);
        }
    }*/
    //  프로젝트 역할을 생성한다.
    private ProjectRole addProjectRole(Project project, String projectRoleName, String projectRoleType, String permissionType) {
        ProjectRole projectRole = new ProjectRole(project, projectRoleName, projectRoleType);
src/main/java/kr/wisestone/owl/service/impl/ProjectRoleUserServiceImpl.java
@@ -54,6 +54,13 @@
        return this.projectRoleUserRepository.findByProjectRoleIdAndUserId(projectRoleId, userId);
    }
    //  해당 부서가 특정 역할에 소속되어 있는지 확인한다.
    @Override
    @Transactional(readOnly = true)
    public ProjectRoleUser findByProjectRoleIdAndDepartmentId(Long projectRoleId, Long departmentId) {
        return this.projectRoleUserRepository.findByProjectRoleIdAndDepartmentId(projectRoleId, departmentId);
    }
    //  업무 공간을 탈퇴한 사용자가 다른 업무 공간의 프로젝트 관리자, 일반 사용자로 있을 경우 제거한다.
    @Override
    @Transactional
src/main/java/kr/wisestone/owl/web/condition/IssueCondition.java
@@ -39,6 +39,7 @@
    private List<Long> priorityIds = Lists.newArrayList();
    private List<Long> severityIds = Lists.newArrayList();
    private List<Long> userIds = Lists.newArrayList();
    private List<Long> departmentIds = Lists.newArrayList();
    private List<Long> registerIds = Lists.newArrayList();
    private List<String> issueIds = Lists.newArrayList();   //  이슈 목록 검색에서 사용자 정의 필드로 1차 검색한 결과를 담을때 사용
    private List<Map<String, Object>> issueCustomFields = Lists.newArrayList();
@@ -136,6 +137,10 @@
        if (MapUtil.getLongs(conditions, "userIds") != null) {
            condition.setUserIds(MapUtil.getLongs(conditions, "userIds"));
        }
        if (MapUtil.getLongs(conditions, "departmentIds") != null) {
            condition.setDepartmentIds(MapUtil.getLongs(conditions, "departmentIds"));
        }
        if (MapUtil.getLongs(conditions, "registerIds") != null) {
@@ -317,6 +322,14 @@
        this.userIds = userIds;
    }
    public List<Long> getDepartmentIds() {
        return departmentIds;
    }
    public void setDepartmentIds(List<Long> departmentIds) {
        this.departmentIds = departmentIds;
    }
    public List<Long> getRegisterIds() {
        return registerIds;
    }
src/main/java/kr/wisestone/owl/web/controller/IssueUserController.java
@@ -32,7 +32,8 @@
        IssueForm issueForm = IssueForm.make(params.get(Constants.REQ_KEY_CONTENT));
        if (issueForm != null) {
            this.issueService.modifyIssueUser(issueForm);
            //this.issueService.modifyIssueUser(issueForm);
            this.issueService.modifyIssueDepartment(issueForm);
        }
        return this.setSuccessMessage(resJsonData);
src/main/java/kr/wisestone/owl/web/form/IssueForm.java
@@ -28,6 +28,7 @@
    private Long issueNumber;
    private Long registerId;    //  등록자 아이디 - issue insert batch 에서 사용
    private List<Long> userIds = Lists.newArrayList();
    private List<Long> departmentIds = Lists.newArrayList();    // 담당 부서
    private List<String> sendEmails = Lists.newArrayList(); //  이메일 발송 대상자
    private List<Long> attachedFileIds = Lists.newArrayList();
    private Long relationIssue;   // 연관 일감
@@ -55,6 +56,11 @@
        //  담당자 정보
        if (MapUtil.getLongs(params, "userIds") != null) {
            form.setUserIds(MapUtil.getLongs(params, "userIds"));
        }
        //  담당부서 정보
        if (MapUtil.getLongs(params, "departmentIds") != null) {
            form.setDepartmentIds(MapUtil.getLongs(params, "departmentIds"));
        }
        //  메일 발송자 정보
@@ -182,6 +188,14 @@
        this.userIds = userIds;
    }
    public List<Long> getDepartmentIds() {
        return departmentIds;
    }
    public void setDepartmentIds(List<Long> departmentIds) {
        this.departmentIds = departmentIds;
    }
    public List<Long> getRemoveFiles() {
        return removeFiles;
    }
src/main/resources/migration/V1_1__Initial_Setup.sql
@@ -512,7 +512,8 @@
CREATE TABLE IF NOT EXISTS `project_role_user` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `project_role_id` bigint(20) NOT NULL,
    `user_id` bigint(20) NOT NULL,
    `user_id` bigint(20) NULL,
    `department_id` bigint(20) NULL,
    `register_id` bigint(20) NOT NULL,
    `register_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    `modify_id` bigint(20) NOT NULL,
@@ -520,7 +521,8 @@
    PRIMARY KEY (`id`),
    KEY `projectRoleIdAndUserIdIndex` (`project_role_id`,`user_id`),
    KEY `userIdIndex` (`user_id`),
    KEY `projectRoleIdIndex` (`project_role_id`)
    KEY `projectRoleIdIndex` (`project_role_id`),
    KEY `departmentIdIndex` (`department_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 테이블 데이터 owl_en_1.5.project_role_user:~0 rows (대략적) 내보내기
src/main/resources/mybatis/query-template/issueUser-template.xml
@@ -6,13 +6,41 @@
    <!--    이슈 담당자 bulk insert, import, modify, add 에서 사용 -->
    <insert id="insertIssueUser" keyColumn="id" keyProperty="id" useGeneratedKeys="true"
            parameterType="java.util.HashMap">
        INSERT INTO issue_user(user_id, issue_id, workspace_id, register_id, modify_id, register_date, modify_date)
        INSERT INTO issue_user(department_id, user_id, issue_id, workspace_id, register_id, modify_id, register_date, modify_date)
        VALUES
        <foreach collection="list" item="map" index="index" separator="," open="" close="">
            (#{map.userId}, #{map.issueId}, #{map.workspaceId}, #{map.registerId}, #{map.registerId}, NOW(), NOW())
            (#{map.departmentId},#{map.userId}, #{map.issueId}, #{map.workspaceId}, #{map.registerId}, #{map.registerId}, NOW(), NOW())
        </foreach>
    </insert>
    <!--담당부서-->
    <!--    이슈 담당부서 bulk 삭제 - modify, add 에서 사용  -->
    <delete id="deleteIssueUserByIssueIdAndMultiDepartmentId" parameterType="java.util.HashMap">
        DELETE FROM issue_user WHERE issue_id = #{issueId} AND department_id IN (
        <foreach collection="map.departmentIds" item="item" index="index" separator="," open="" close="">
            #{item}
        </foreach>
        )
    </delete>
    <delete id="deleteIssueUserByDepartmentIdAndMultiIssueId" parameterType="java.util.HashMap">
        DELETE FROM issue_user WHERE department_id = #{departmentId} AND issue_id IN (
        <foreach collection="issueIds" item="item" index="index" separator="," open="" close="">
            #{item}
        </foreach>
        )
    </delete>
    <!--    이슈 담당부서를 조회한다 -->
    <select id="findByDepartmentIdAndProjectId" resultType="java.util.HashMap" parameterType="java.util.HashMap">
        SELECT DISTINCT(i.id) FROM issue i
                                       INNER JOIN issue_user iu ON iu.issue_id = i.id
                                       INNER JOIN department d ON d.id = iu.department_id
        WHERE i.project_id = #{projectId} AND d.id = #{departmentId}
    </select>
    <!--담당자-->
    <!--    이슈 담당자 bulk 삭제 - modify, add 에서 사용  -->
    <delete id="deleteIssueUserByIssueIdAndMultiUserId" parameterType="java.util.HashMap">
        DELETE FROM issue_user WHERE issue_id = #{issueId} AND user_id IN (
@@ -30,9 +58,6 @@
        )
    </delete>
    <!--    이슈 담당자를 조회한다 -->
    <select id="findByUserIdAndProjectId" resultType="java.util.HashMap" parameterType="java.util.HashMap">
      SELECT DISTINCT(i.id) FROM issue i
@@ -40,6 +65,5 @@
        INNER JOIN user u ON u.id = iu.user_id
        WHERE i.project_id = #{projectId} AND u.id = #{userId}
    </select>
</mapper>
src/main/webapp/WEB-INF/i18n/code_ko_KR.properties
@@ -17,6 +17,7 @@
common.priority=\uC6B0\uC120\uC21C\uC704
common.importance=\uC911\uC694\uB3C4
common.assignee=\uB2F4\uB2F9\uC790
common.department=\uB2F4\uB2F9\uBD80\uC11C
common.period=\uAE30\uAC04
common.register=\uB4F1\uB85D\uC790
common.modifyDate=\uCD5C\uC885 \uBCC0\uACBD\uC77C