From b2bf222751b9bba2315f861c2c5a2511dad86626 Mon Sep 17 00:00:00 2001
From: 이민희 <mhlee@maprex.co.kr>
Date: 화, 23 11월 2021 21:34:43 +0900
Subject: [PATCH] 이력 남기기

---
 src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java         |   69 +++++--
 src/main/java/kr/wisestone/owl/service/impl/IssueRiskServiceImpl.java     |   44 ++++
 src/main/java/kr/wisestone/owl/service/impl/WidgetServiceImpl.java        |   16 +
 src/main/java/kr/wisestone/owl/service/IssueHistoryService.java           |   11 +
 src/main/java/kr/wisestone/owl/service/impl/IssueRelationServiceImpl.java |    4 
 src/main/java/kr/wisestone/owl/service/IssueRiskService.java              |    3 
 src/main/resources/mybatis/query-template/issue-template.xml              |    4 
 src/main/java/kr/wisestone/owl/service/impl/IssueHostingServiceImpl.java  |   13 +
 src/main/java/kr/wisestone/owl/domain/Issue.java                          |    1 
 src/main/java/kr/wisestone/owl/service/impl/IssueCompanyServiceImpl.java  |   15 +
 src/main/resources/migration/V1_11__Alter_Table.sql                       |    3 
 src/main/java/kr/wisestone/owl/domain/IssueRisk.java                      |    9 +
 src/main/java/kr/wisestone/owl/mapper/WidgetMapper.java                   |    3 
 src/main/webapp/i18n/ko/global.json                                       |   28 +++
 src/main/resources/mybatis/query-template/widget-template.xml             |   52 +++++
 src/main/java/kr/wisestone/owl/service/impl/IssueIspServiceImpl.java      |   13 +
 src/main/java/kr/wisestone/owl/service/impl/IssueHistoryServiceImpl.java  |  199 +++++++++++++++++++++
 17 files changed, 444 insertions(+), 43 deletions(-)

diff --git a/src/main/java/kr/wisestone/owl/domain/Issue.java b/src/main/java/kr/wisestone/owl/domain/Issue.java
index 6f57e22..9482365 100644
--- a/src/main/java/kr/wisestone/owl/domain/Issue.java
+++ b/src/main/java/kr/wisestone/owl/domain/Issue.java
@@ -15,6 +15,7 @@
     public static final String PROJECT_MANAGER = "PROJECT_MANAGER"; //  �봽濡쒖젥�듃 愿�由ъ옄
     public static final String REGISTER = "REGISTER";   //  �씠�뒋 �벑濡앹옄
     public static final String ASSIGNEE = "ASSIGNEE";   //  �씠�뒋 �떞�떦�옄
+    public static final String DEPARTMENT = "DEPARTMENT";   //  �씠�뒋 �떞�떦遺��꽌
 
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
diff --git a/src/main/java/kr/wisestone/owl/domain/IssueRisk.java b/src/main/java/kr/wisestone/owl/domain/IssueRisk.java
index 49e1d26..4774e73 100644
--- a/src/main/java/kr/wisestone/owl/domain/IssueRisk.java
+++ b/src/main/java/kr/wisestone/owl/domain/IssueRisk.java
@@ -14,6 +14,7 @@
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id;
     private Long changeAssigneeCount;
+    private Long changeDepartmentCount;
     private Long changeIssueStatusCount;
     private String issueStatusIds;
 
@@ -74,4 +75,12 @@
     public void setWorkspace(Workspace workspace) {
         this.workspace = workspace;
     }
+
+    public Long getChangeDepartmentCount() {
+        return changeDepartmentCount;
+    }
+
+    public void setChangeDepartmentCount(Long changeDepartmentCount) {
+        this.changeDepartmentCount = changeDepartmentCount;
+    }
 }
diff --git a/src/main/java/kr/wisestone/owl/mapper/WidgetMapper.java b/src/main/java/kr/wisestone/owl/mapper/WidgetMapper.java
index 86575ca..46fdab8 100644
--- a/src/main/java/kr/wisestone/owl/mapper/WidgetMapper.java
+++ b/src/main/java/kr/wisestone/owl/mapper/WidgetMapper.java
@@ -61,7 +61,8 @@
 
     //  �쐞�뿕 愿�由�
     List<Map<String, Object>> findRiskIssue(WidgetCondition widgetCondition);
-    Map<String, Object> countChangeStatusAndAssigneeIssue(WidgetCondition widgetCondition);
+    //Map<String, Object> countChangeStatusAndAssigneeIssue(WidgetCondition widgetCondition);
+    Map<String, Object> countChangeStatusAndDepartmentIssue(WidgetCondition widgetCondition);
     Long countRiskIssue(WidgetCondition widgetCondition);
 
     //  �쟾泥� �씠�뒋 泥섎━ �쁽�솴
diff --git a/src/main/java/kr/wisestone/owl/service/IssueHistoryService.java b/src/main/java/kr/wisestone/owl/service/IssueHistoryService.java
index 47bf34f..f9417a5 100644
--- a/src/main/java/kr/wisestone/owl/service/IssueHistoryService.java
+++ b/src/main/java/kr/wisestone/owl/service/IssueHistoryService.java
@@ -4,6 +4,7 @@
 import kr.wisestone.owl.domain.enumType.IssueHistoryType;
 import kr.wisestone.owl.service.impl.IssueHistoryServiceImpl;
 import kr.wisestone.owl.vo.IssueHistoryVo;
+import kr.wisestone.owl.vo.IssueVo;
 import kr.wisestone.owl.web.condition.IssueHistoryCondition;
 import kr.wisestone.owl.web.form.IssueForm;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -43,12 +44,22 @@
 
     void detectIssueManager(Issue issue, IssueForm issueForm, StringBuilder description);
 
+    void detectIssueDepartment(Issue issue, IssueForm issueForm, StringBuilder description);
+
     void detectAttachedFile(IssueForm issueForm, StringBuilder description, List<MultipartFile> files);
 
     void detectCustomField(Issue issue, IssueForm issueForm, StringBuilder description);
 
     void detectRelationIssue(IssueHistoryType type, IssueRelation issueRelation, StringBuilder description);
 
+    void detectDownIssues(IssueHistoryType type, Issue issue, StringBuilder description);
+
+    void detectIssueCompany(IssueHistoryType type, Map<String, Object> param, IssueCompany issueCompany, StringBuilder description);
+
+    void detectIssueIsp(IssueHistoryType type, Map<String, Object> param, IssueIsp issueIsp, StringBuilder description);
+
+    void detectIssueHosting(IssueHistoryType type, Map<String, Object> param, IssueHosting issueHosting, StringBuilder description);
+
     void recodeRemoveCustomFieldOptionValue(CustomField customField, String oldValue, String newValue, StringBuilder description);
 
     void recodeChangeCustomFieldType(CustomField customField, String oldValue, StringBuilder description);
diff --git a/src/main/java/kr/wisestone/owl/service/IssueRiskService.java b/src/main/java/kr/wisestone/owl/service/IssueRiskService.java
index 342ace2..dc06545 100644
--- a/src/main/java/kr/wisestone/owl/service/IssueRiskService.java
+++ b/src/main/java/kr/wisestone/owl/service/IssueRiskService.java
@@ -9,5 +9,6 @@
 
     IssueRisk addIssueRisk(Issue issue, Workspace workspace);
 
-    void modifyIssueRisk(Issue issue, Boolean changeIssueStatus, Boolean changeAssignee, Long issueStatusId);
+    //void modifyIssueRisk(Issue issue, Boolean changeIssueStatus, Boolean changeAssignee, Long issueStatusId);
+    void modifyIssueRisk(Issue issue, Boolean changeIssueStatus, Boolean changeDepartment, Long issueStatusId);
 }
diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueCompanyServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueCompanyServiceImpl.java
index a24332f..94e0681 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueCompanyServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueCompanyServiceImpl.java
@@ -1,6 +1,7 @@
 package kr.wisestone.owl.service.impl;
 
 import kr.wisestone.owl.domain.*;
+import kr.wisestone.owl.domain.enumType.IssueHistoryType;
 import kr.wisestone.owl.mapper.IssueCompanyMapper;
 import kr.wisestone.owl.repository.IssueCompanyRepository;
 import kr.wisestone.owl.service.*;
@@ -28,6 +29,9 @@
     private CompanyFieldService companyFieldService;
 
     @Autowired
+    private IssueHistoryService issueHistoryService;
+
+    @Autowired
     private IssueCompanyMapper issueCompanyMapper;
 
     @Override
@@ -48,9 +52,13 @@
 
                     Set<IssueCompany> issueCompanies = issue.getIssueCompanies();
                     IssueCompany issueCompany = null;
-
                     if (issueCompanies != null && issueCompanies.size() > 0) { //�닔�젙 �븷 寃쎌슦
                         issueCompany = issueCompanies.iterator().next();
+                        // 蹂�寃� �씠�젰
+                        StringBuilder sb = new StringBuilder();
+                        issueHistoryService.detectIssueCompany(IssueHistoryType.MODIFY, param, issueCompany, sb);
+                        issueHistoryService.addIssueHistory(issue, IssueHistoryType.MODIFY, sb.toString());
+
                         issueCompany.setCompanyField(companyField);
                         issueCompany.setName(MapUtil.getString(param, "name"));
                         issueCompany.setEmail(MapUtil.getString(param, "email"));
@@ -61,8 +69,13 @@
                         issueCompany = ConvertUtil.convertMapToClass(param, IssueCompany.class);
                         issueCompany.setIssue(issue);
                         issueCompany.setCompanyField(companyField);
+                        // 異붽� �씠�젰
+                        StringBuilder sb = new StringBuilder();
+                        issueHistoryService.detectIssueCompany(IssueHistoryType.ADD, param, issueCompany, sb);
+                        issueHistoryService.addIssueHistory(issue, IssueHistoryType.MODIFY, sb.toString());
                     }
                     this.issueCompanyRepository.saveAndFlush(issueCompany);
+
                 }
             }
         }
diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueHistoryServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueHistoryServiceImpl.java
index c6dce73..fc67609 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueHistoryServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueHistoryServiceImpl.java
@@ -13,6 +13,7 @@
 import kr.wisestone.owl.service.*;
 import kr.wisestone.owl.util.*;
 import kr.wisestone.owl.vo.IssueHistoryVo;
+import kr.wisestone.owl.vo.IssueVo;
 import kr.wisestone.owl.web.condition.IssueHistoryCondition;
 import kr.wisestone.owl.web.form.IssueForm;
 import org.apache.commons.lang3.StringUtils;
@@ -37,6 +38,9 @@
 
     @Autowired
     private UserService userService;
+
+    @Autowired
+    private DepartmentService departmentService;
 
     @Autowired
     private IssueHistoryMapper issueHistoryMapper;
@@ -292,7 +296,9 @@
         //  �씠�뒋 湲곌컙 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
         this.detectIssuePeriod(issue, issueForm, description);
         //  �떞�떦�옄 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
-        //this.detectIssueManager(issue, issueForm, description);
+        this.detectIssueManager(issue, issueForm, description);
+        //  �떞�떦遺��꽌 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
+        this.detectIssueDepartment(issue, issueForm, description);
         //  �궗�슜�옄 �젙�쓽 �븘�뱶 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
         this.detectCustomField(issue, issueForm, description);
 
@@ -447,10 +453,8 @@
         else {
             recodeIssuePeriod.append("<span translate=\"common.unspecified\">誘몄��젙</span>");
         }
-
         return recodeIssuePeriod.toString();
     }
-
 
     // �뿰愿� �씪媛� 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
     @Override
@@ -462,6 +466,123 @@
            description.append("<span translate=\"issue.relationIssueRemoveHistory\">�뿰愿� �씪媛먯씠 �궘�젣�릺�뿀�뒿�땲�떎. " + issueRelation.getRelationIssue().getTitle() + "</span>");
            description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueRelation.getRelationIssue().getTitle() + "</span>");
        }
+    }
+
+    // �븯�쐞 �씪媛� 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
+    @Override
+    public void detectDownIssues(IssueHistoryType type, Issue issue, StringBuilder description) {
+        if (type == IssueHistoryType.ADD) {
+            description.append("<span translate=\"issue.downIssueAddHistory\">�븯�쐞 �씪媛먯씠 異붽��릺�뿀�뒿�땲�떎. </span>");
+            description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issue.getTitle() + "</span>");
+        }else {
+            description.append("<span translate=\"issue.downIssueRemoveHistory\">�븯�쐞 �씪媛먯씠 �궘�젣�릺�뿀�뒿�땲�떎. </span>");
+            description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issue.getTitle() + "</span>");
+        }
+    }
+
+    // �뾽泥� �젙蹂� 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
+    @Override
+    public void detectIssueCompany(IssueHistoryType type, Map<String, Object> param, IssueCompany issueCompany, StringBuilder description) {
+        Long id = MapUtil.getLong(param, "id");
+
+        if (type == IssueHistoryType.ADD) { //異붽� �븷 寃쎌슦
+            description.append("<span translate=\"issue.issueCompanyAddHistory\">�뾽泥� �젙蹂닿� 異붽��릺�뿀�뒿�땲�떎. </span>");
+            description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueCompany.getCompanyField().getName() + "</span>");
+        } else if (type == IssueHistoryType.MODIFY) { //�닔�젙 �븷 寃쎌슦
+            if (id != null && !issueCompany.getId().equals(id)) {
+                description.append("<span translate=\"issue.issueCompanyModifyHistory\">�뾽泥� �젙蹂닿� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueCompany.getCompanyField().getName() + "</span>");
+            }
+            if (param.get("manager") != null && (issueCompany.getManager() == null || !issueCompany.getManager().equals(param.get("manager")))) {
+                description.append("<span translate=\"issue.issueCompanyModifyManagerHistory\">&nbsp;>&nbsp;�뾽泥� �젙蹂댁쓽 �떞�떦�옄媛� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("manager") + "</span>");
+            }
+            if (param.get("tel") != null && (issueCompany.getTel() == null || !issueCompany.getTel().equals(param.get("tel")))) {
+                description.append("<span translate=\"issue.issueCompanyModifyTelHistory\">&nbsp;>&nbsp;�뾽泥� �젙蹂댁쓽 �쟾�솕踰덊샇媛� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("tel") + "</span>");
+            }
+            if (param.get("email") != null && (issueCompany.getEmail() == null || !issueCompany.getEmail().equals(param.get("email")))) {
+                description.append("<span translate=\"issue.issueCompanyModifyEmailHistory\">&nbsp;>&nbsp;�뾽泥� �젙蹂댁쓽 �씠硫붿씪�씠 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("email") + "</span>");
+            }
+            if (param.get("memo") != null && (issueCompany.getMemo() == null || !issueCompany.getMemo().equals(param.get("memo")))) {
+                description.append("<span translate=\"issue.issueCompanyModifyMemoHistory\">&nbsp;>&nbsp;�뾽泥� �젙蹂댁쓽 鍮꾧퀬媛� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("memo") + "</span>");
+            }
+        } else {
+            description.append("<span translate=\"issue.issueCompanyRemoveHistory\">�뾽泥� �젙蹂닿� �궘�젣�릺�뿀�뒿�땲�떎. " + issueCompany.getCompanyField().getName() + "</span>");
+            description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueCompany.getCompanyField().getName() + "</span>");
+        }
+    }
+
+    // ISP �젙蹂� 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
+    @Override
+    public void detectIssueIsp(IssueHistoryType type, Map<String, Object> param, IssueIsp issueIsp, StringBuilder description) {
+        Long id = MapUtil.getLong(param, "id");
+
+        if (type == IssueHistoryType.ADD) {
+            description.append("<span translate=\"issue.issueIspAddHistory\">ISP �젙蹂닿� 異붽��릺�뿀�뒿�땲�떎. </span>");
+            description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueIsp.getIspField().getName() + "</span>");
+        } else if (type == IssueHistoryType.MODIFY) {
+            if (id != null && !issueIsp.getId().equals(id)) { //�닔�젙 �븷 寃쎌슦
+                description.append("<span translate=\"issue.issueIspModifyHistory\">ISP �젙蹂닿� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueIsp.getIspField().getName() + "</span>");
+            }
+            if (param.get("manager") != null && (issueIsp.getManager() == null || !issueIsp.getManager().equals(param.get("manager")))) {
+                description.append("<span translate=\"issue.issueIspModifyManagerHistory\">ISP �젙蹂댁쓽 �떞�떦�옄媛� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("manager") + "</span>");
+            }
+            if (param.get("tel") != null && (issueIsp.getTel() == null || !issueIsp.getTel().equals(param.get("tel")))) {
+                description.append("<span translate=\"issue.issueIspModifyTelHistory\">ISP �젙蹂댁쓽 �쟾�솕踰덊샇媛� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("tel") + "</span>");
+            }
+            if (param.get("email") != null && (issueIsp.getEmail() == null || !issueIsp.getEmail().equals(param.get("email")))) {
+                description.append("<span translate=\"issue.issueIspModifyEmailHistory\">ISP �젙蹂댁쓽 �씠硫붿씪�씠 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("email") + "</span>");
+            }
+            if (param.get("memo") != null && (issueIsp.getMemo() == null || !issueIsp.getMemo().equals(param.get("memo")))) {
+                description.append("<span translate=\"issue.issueIspModifyMemoHistory\">ISP �젙蹂댁쓽 鍮꾧퀬媛� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("memo") + "</span>");
+            }
+        } else {
+            description.append("<span translate=\"issue.issueIspRemoveHistory\">ISP �젙蹂닿� �궘�젣�릺�뿀�뒿�땲�떎. " + issueIsp.getIspField().getName() + "</span>");
+            description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueIsp.getIspField().getName() + "</span>");
+        }
+    }
+
+    // �샇�뒪�똿 �젙蹂� 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
+    @Override
+    public void detectIssueHosting(IssueHistoryType type, Map<String, Object> param, IssueHosting issueHosting, StringBuilder description) {
+        Long id = MapUtil.getLong(param, "id");
+
+        if (type == IssueHistoryType.ADD) {
+            description.append("<span translate=\"issue.issueHostingAddHistory\">�샇�뒪�똿 �젙蹂닿� 異붽��릺�뿀�뒿�땲�떎. </span>");
+            description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueHosting.getHostingField().getName() + "</span>");
+        }else if(type == IssueHistoryType.MODIFY){
+            if(id != null && !issueHosting.getId().equals(id)){ //�닔�젙 �븷 寃쎌슦
+                description.append("<span translate=\"issue.issueHostingModifyHistory\">�샇�뒪�똿 �젙蹂닿� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueHosting.getHostingField().getName() + "</span>");
+            }
+            if(param.get("manager") != null && (issueHosting.getManager() == null || !issueHosting.getManager().equals(param.get("manager")))){
+                description.append("<span translate=\"issue.issueHostingModifyManagerHistory\">�샇�뒪�똿 �젙蹂댁쓽 �떞�떦�옄媛� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("manager") + "</span>");
+            }
+            if(param.get("tel") != null && (issueHosting.getTel() == null || !issueHosting.getTel().equals(param.get("tel")))){
+                description.append("<span translate=\"issue.issueHostingModifyTelHistory\">�샇�뒪�똿 �젙蹂댁쓽 �쟾�솕踰덊샇媛� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("tel") + "</span>");
+            }
+            if(param.get("email") != null && (issueHosting.getEmail() == null || !issueHosting.getEmail().equals(param.get("email")))){
+                description.append("<span translate=\"issue.issueHostingModifyEmailHistory\">�샇�뒪�똿 �젙蹂댁쓽 �씠硫붿씪�씠 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("email") + "</span>");
+            }
+            if(param.get("memo") != null && (issueHosting.getMemo() == null || !issueHosting.getMemo().equals(param.get("memo")))){
+                description.append("<span translate=\"issue.issueHostingModifyMemoHistory\">�샇�뒪�똿 �젙蹂댁쓽 鍮꾧퀬媛� 蹂�寃쎈릺�뿀�뒿�땲�떎. </span>");
+                description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + param.get("memo") + "</span>");
+            }
+        } else {
+            description.append("<span translate=\"issue.issueHostingRemoveHistory\">�샇�뒪�똿 �젙蹂닿� �궘�젣�릺�뿀�뒿�땲�떎. " + issueHosting.getHostingField().getName() + "</span>");
+            description.append("<span class=\"text-primary bold\">&nbsp;>&nbsp;" + issueHosting.getHostingField().getName() + "</span>");
+        }
     }
 
     //  �떞�떦�옄 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
@@ -537,6 +658,78 @@
         this.makeIssueHistoryHtml(description, title, beforeUser.toString(), afterUser.toString());
     }
 
+    //  �떞�떦遺��꽌 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
+    @Override
+    public void detectIssueDepartment(Issue issue, IssueForm issueForm, StringBuilder description) {
+        boolean saveIssueRisk = false;  //  �씠�뒋 �쐞�뿕 愿�由ъ뿉 �씠以� ���옣�릺�뒗 寃껋쓣 諛⑹��븯湲� �쐞�븳 援щ텇 媛�
+
+        //  �떞�떦遺��꽌 �닔媛� �떖�씪議뚯쓣 寃쎌슦
+        if(issue.getIssueDepartments().size() != issueForm.getDepartmentIds().size()){
+            this.recodeIssueDepartment(issue, issueForm, description);
+            // �씠�뒋 �쐞�뿕 愿�由ъ뿉 �떞�떦遺��꽌 蹂�寃� �젙蹂대�� �뾽�뜲�씠�듃 �븳�떎. - �떞�떦遺��꽌 蹂�寃�
+            this.issueRiskService.modifyIssueRisk(issue, false, true, null);
+            saveIssueRisk = true;
+        }
+
+        //  �떞�떦遺��꽌 �닔�뒗 媛숈쑝�굹 �떞�떦遺��꽌媛� �떖�씪議뚯쓣 寃쎌슦
+        if (issue.getIssueDepartments().size() > 0 && issueForm.getDepartmentIds().size() > 0) {
+            //  �씠�쟾 �떞�떦�옄 �몴�떆
+            for (IssueDepartment issueDepartment : issue.getIssueDepartments()) {
+                boolean change = true;
+                Department department = issueDepartment.getDepartment();
+
+                for (Long departmentId : issueForm.getDepartmentIds()) {
+                    if (department.getId().equals(departmentId)) {
+                        change = false;
+                        break;
+                    }
+                }
+
+                if (change) {
+                    //  �떞�떦遺��꽌 蹂�寃� �젙蹂� 湲곕줉
+                    this.recodeIssueDepartment(issue, issueForm, description);
+                    //  �떞�떦遺��꽌 �닔媛� �떖�씪議뚯쓣 寃쎌슦�뿉 ���옣�릺吏� �븡�븯�떎硫� �뿬湲곗꽌 �씠�뒋 �쐞�뿕 愿�由� ���옣�쓣 �븳�떎.
+                    if (!saveIssueRisk) {
+                        //  �씠�뒋 �쐞�뿕 愿�由ъ뿉 �떞�떦遺��꽌 蹂�寃� �젙蹂대�� �뾽�뜲�씠�듃�븳�떎. - �떞�떦遺��꽌 蹂�寃�
+                        this.issueRiskService.modifyIssueRisk(issue, false, true, null);
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
+    //  �떞�떦遺��꽌 蹂�寃� �젙蹂� 湲곕줉
+    private void recodeIssueDepartment(Issue issue, IssueForm issueForm, StringBuilder description) {
+        String title = "<span translate=\"common.updateDepartment\">�떞�떦遺��꽌媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.</span>";
+        StringBuilder beforeDepartment = new StringBuilder();
+
+        //  �씠�쟾 �떞�떦遺��꽌 �몴�떆
+        for (IssueDepartment issueDepartment : issue.getIssueDepartments()) {
+            beforeDepartment.append(issueDepartment.getDepartment().getDepartmentName());
+            beforeDepartment.append(", ");
+        }
+        //  �떞�떦遺��꽌媛� �뾾�뿀�쑝硫� �뾾�쓬�쑝濡� �몴�떆
+        if (issue.getIssueDepartments().size() < 1) {
+            beforeDepartment.append("<span translate=\"common.none\">�뾾�쓬</span>");
+        }
+
+        StringBuilder afterDepartment = new StringBuilder();
+        for (Long departmentId : issueForm.getDepartmentIds()) {
+            Department department = this.departmentService.getDepartment(departmentId);
+            afterDepartment.append(department.getDepartmentName());
+            afterDepartment.append(", ");
+        }
+
+        //  �떞�떦遺��꽌媛� �뾾�뿀�쑝硫� �뾾�쓬�쑝濡� �몴�떆
+        if (issueForm.getDepartmentIds().size() < 1) {
+            afterDepartment.append("<span translate=\"common.none\">�뾾�쓬</span>");
+        }
+
+        //  �씠�젰 �젙蹂대�� html �깭洹몃줈 留뚮뱾�뼱 以��떎.
+        this.makeIssueHistoryHtml(description, title, beforeDepartment.toString(), afterDepartment.toString());
+    }
+
     //  �씠�뒋�뿉 泥⑤��맂 �뙆�씪�뿉 ���빐 蹂�寃� �젙蹂대�� 湲곕줉�븳�떎.
     @Override
     public void detectAttachedFile(IssueForm issueForm, StringBuilder description, List<MultipartFile> files) {
diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueHostingServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueHostingServiceImpl.java
index de7fd64..9437299 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueHostingServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueHostingServiceImpl.java
@@ -1,6 +1,7 @@
 package kr.wisestone.owl.service.impl;
 
 import kr.wisestone.owl.domain.*;
+import kr.wisestone.owl.domain.enumType.IssueHistoryType;
 import kr.wisestone.owl.mapper.HostingFieldMapper;
 import kr.wisestone.owl.mapper.IssueHostingMapper;
 import kr.wisestone.owl.repository.IssueHostingRepository;
@@ -30,6 +31,9 @@
     private HostingFieldService hostingFieldService;
 
     @Autowired
+    private IssueHistoryService issueHistoryService;
+
+    @Autowired
     private IssueHostingMapper issueHostingMapper;
 
     @Override
@@ -53,6 +57,11 @@
 
                     if (issueHostings != null && issueHostings.size() >0){//�닔�젙 �븷 寃쎌슦
                         issueHosting = issueHostings.iterator().next();
+                        // 蹂�寃� �씠�젰
+                        StringBuilder sb = new StringBuilder();
+                        issueHistoryService.detectIssueHosting(IssueHistoryType.MODIFY, param, issueHosting, sb);
+                        issueHistoryService.addIssueHistory(issue, IssueHistoryType.MODIFY, sb.toString());
+
                         issueHosting.setHostingField(hostingField);
                         issueHosting.setName(MapUtil.getString(param, "name"));
                         issueHosting.setEmail(MapUtil.getString(param, "email"));
@@ -64,6 +73,10 @@
                         issueHosting = ConvertUtil.convertMapToClass(param, IssueHosting.class);
                         issueHosting.setIssue(issue);
                         issueHosting.setHostingField(hostingField);
+                        // 異붽� �씠�젰
+                        StringBuilder sb = new StringBuilder();
+                        issueHistoryService.detectIssueHosting(IssueHistoryType.ADD, param, issueHosting, sb);
+                        issueHistoryService.addIssueHistory(issue, IssueHistoryType.MODIFY, sb.toString());
                     }
                     this.issueHostingRepository.saveAndFlush(issueHosting);
                 }
diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueIspServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueIspServiceImpl.java
index 2b7f339..2cd7eef 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueIspServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueIspServiceImpl.java
@@ -1,6 +1,7 @@
 package kr.wisestone.owl.service.impl;
 
 import kr.wisestone.owl.domain.*;
+import kr.wisestone.owl.domain.enumType.IssueHistoryType;
 import kr.wisestone.owl.mapper.IssueIspMapper;
 import kr.wisestone.owl.repository.IssueIspRepository;
 import kr.wisestone.owl.service.*;
@@ -28,6 +29,9 @@
     private IspFieldService ispFieldService;
 
     @Autowired
+    private IssueHistoryService issueHistoryService;
+
+    @Autowired
     private IssueIspMapper issueIspMapper;
 
     @Override
@@ -51,6 +55,11 @@
 
                     if (issueIsps != null && issueIsps.size() > 0) {//�닔�젙 �븷 寃쎌슦
                         issueIsp = issueIsps.iterator().next();
+                        // 蹂�寃� �씠�젰
+                        StringBuilder sb = new StringBuilder();
+                        issueHistoryService.detectIssueIsp(IssueHistoryType.MODIFY, param, issueIsp, sb);
+                        issueHistoryService.addIssueHistory(issue, IssueHistoryType.MODIFY, sb.toString());
+
                         issueIsp.setIspField(ispField);
                         issueIsp.setName(MapUtil.getString(param, "name"));
                         issueIsp.setEmail(MapUtil.getString(param, "email"));
@@ -62,6 +71,10 @@
                         issueIsp = ConvertUtil.convertMapToClass(param, IssueIsp.class);
                         issueIsp.setIssue(issue);
                         issueIsp.setIspField(ispField);
+                        // 異붽� �씠�젰
+                        StringBuilder sb = new StringBuilder();
+                        issueHistoryService.detectIssueIsp(IssueHistoryType.ADD, param, issueIsp, sb);
+                        issueHistoryService.addIssueHistory(issue, IssueHistoryType.MODIFY, sb.toString());
                     }
                     this.issueIspRepository.saveAndFlush(issueIsp);
                 }
diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueRelationServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueRelationServiceImpl.java
index c613a5d..3782207 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueRelationServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueRelationServiceImpl.java
@@ -55,10 +55,6 @@
             issueRelation.setRelationIssueType(condition.getRelationIssueType());
 
             issueRelationRepository.saveAndFlush(issueRelation);
-
-            StringBuilder sb = new StringBuilder();
-            issueHistoryService.detectRelationIssue(IssueHistoryType.ADD, issueRelation, sb);
-            issueHistoryService.addIssueHistory(issue, IssueHistoryType.MODIFY, sb.toString());
         }
     }
 
diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueRiskServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueRiskServiceImpl.java
index fcfd3e6..df379a6 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueRiskServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueRiskServiceImpl.java
@@ -34,6 +34,7 @@
         IssueRisk issueRisk = new IssueRisk();
         issueRisk.setChangeIssueStatusCount(0L);
         issueRisk.setChangeAssigneeCount(0L);
+        issueRisk.setChangeDepartmentCount(0L);
         issueRisk.setIssue(issue);
         issueRisk.setWorkspace(workspace);
         issueRisk.setIssueStatusIds(issue.getIssueStatus().getId().toString());
@@ -41,7 +42,7 @@
     }
 
     //  �씠�뒋�뿉�꽌 �떞�떦�옄�굹 �긽�깭媛� 蹂�寃쎈맆 寃쎌슦 �씠�뒋 �쐞�뿕 愿�由� �젙蹂대�� �뾽�뜲�씠�듃�븳�떎.
-    @Override
+    /*@Override
     @Transactional
     public void modifyIssueRisk(Issue issue, Boolean changeIssueStatus, Boolean changeAssignee, Long issueStatusId) {
         IssueRisk issueRisk = issue.getIssueRisk();
@@ -80,5 +81,46 @@
         }
 
         this.issueRiskRepository.saveAndFlush(issueRisk);
+    }*/
+
+    @Override
+    @Transactional
+    public void modifyIssueRisk(Issue issue, Boolean changeIssueStatus, Boolean changeDepartment, Long issueStatusId) {
+        IssueRisk issueRisk = issue.getIssueRisk();
+
+        //  �긽�깭 蹂�寃�
+        if (changeIssueStatus) {
+            String issueStatusIds = issueRisk.getIssueStatusIds();
+            issueStatusIds += "&" + issueStatusId;
+
+            Map<String, Integer> issueStatusIdMaps = new HashMap<>();
+
+            for (String key : issueStatusIds.split("&")) {
+                if (!issueStatusIdMaps.containsKey(key)) {
+                    issueStatusIdMaps.put(key, 1);
+                }
+                else {
+                    issueStatusIdMaps.put(key, issueStatusIdMaps.get(key) + 1);
+                }
+            }
+
+            Integer saveCount = 0;
+
+            for (Integer value : issueStatusIdMaps.values()) {
+                if (value > saveCount) {
+                    saveCount = value;
+                }
+            }
+
+            issueRisk.setChangeIssueStatusCount(saveCount.longValue());
+            issueRisk.setIssueStatusIds(issueStatusIds);
+        }
+
+        //  �떞�떦�옄 蹂�寃�
+        if (changeDepartment) {
+            issueRisk.setChangeDepartmentCount(issueRisk.getChangeDepartmentCount() + 1);
+        }
+
+        this.issueRiskRepository.saveAndFlush(issueRisk);
     }
 }
diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
index 1bb3151..ebf90a3 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -222,6 +222,12 @@
         //this.issueUserService.modifyIssueUser(issue, project.getWorkspace(), issueForm.getUserIds());
         //  �떞�떦遺��꽌 吏��젙
         this.issueDepartmentService.modifyIssueDepartment(issue, project.getWorkspace(), issueForm.getDepartmentIds());
+        //  �뾽泥� �젙蹂� ���옣
+        this.issueCompanyService.modifyIssueCompanyField(issue, issueForm.getIssueCompanyFields());
+        //  ISP �젙蹂� ���옣
+        this.issueIspService.modifyIssueIspField(issue, issueForm.getIssueIspFields());
+        //  HOSTING �젙蹂� ���옣
+        this.issueHostingService.modifyIssueHostingField(issue, issueForm.getIssueHostingFields());
 
         //  multipartFile �쓣 file Map List 媛앹껜濡� 蹂�寃쏀븳�떎.
         List<Map<String, Object>> convertFileMaps = this.convertMultipartFileToFile(multipartFiles);
@@ -241,12 +247,6 @@
         this.reservationIssueEmail(issue.getId(), EmailType.ISSUE_ADD);
         //  �궗�슜�옄 �떆�뒪�뀥 湲곕뒫 �궗�슜 �젙蹂� �닔吏�
         log.info(ElasticSearchUtil.makeUserActiveHistoryMessage(this.webAppUtil.getLoginUser(), ElasticSearchConstants.ISSUE_ADD));
-        //  �뾽泥� �젙蹂� ���옣
-        this.issueCompanyService.modifyIssueCompanyField(issue, issueForm.getIssueCompanyFields());
-        //  ISP �젙蹂� ���옣
-        this.issueIspService.modifyIssueIspField(issue, issueForm.getIssueIspFields());
-        //  HOSTING �젙蹂� ���옣
-        this.issueHostingService.modifyIssueHostingField(issue, issueForm.getIssueHostingFields());
 
         return issue;
     }
@@ -865,7 +865,6 @@
 
     }
 
-
     //  �긽�쐞�씪媛� �젙蹂� 異붽�
     private void setParentIssue(Issue issue, IssueVo issueVo) {
         if(issue.getParentIssue() != null){
@@ -1225,11 +1224,11 @@
         boolean hasPermission = false;
 
         //  �뾽臾� 怨듦컙 愿�由ъ옄�씪 寃쎌슦 �닔�젙 沅뚰븳�쓣 媛뽯뒗�떎.
-        hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.WORKSPACE_MANAGER, issueVo, null);
+        hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.WORKSPACE_MANAGER, issueVo, null, null);
         //  �봽濡쒖젥�듃 愿�由ъ옄�씪 寃쎌슦 �빐�떦 �봽濡쒖젥�듃�뿉 �벑濡앸맂 �씠�뒋�뒗 �닔�젙 沅뚰븳�쓣 媛뽯뒗�떎.
-        hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.PROJECT_MANAGER, issueVo, null);
+        hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.PROJECT_MANAGER, issueVo, null, null);
         //   �씠�뒋 �벑濡앹옄�씪 寃쎌슦 �닔�젙 沅뚰븳�쓣 媛뽯뒗�떎.
-        hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.REGISTER, issueVo, null);
+        hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.REGISTER, issueVo, null, null);
         //  �씠�뒋 �떞�떦�옄�씪 寃쎌슦 �닔�젙 沅뚰븳�쓣 媛뽯뒗�떎. => �떞�떦遺��꽌濡� �닔�젙 - 泥댄겕
         //hasPermission = this.checkIssueModifyPermission(hasPermission, Issue.ASSIGNEE, issueVo, issueUserVos);
         //  �떞�떦�옄媛� �뾾�쑝硫� 紐⑤뱺 �궗�슜�옄媛� �닔�젙 沅뚰븳�쓣 媛뽯뒗�떎.
@@ -1238,7 +1237,7 @@
     }
 
     //  �씠�뒋 �닔�젙 沅뚰븳�쓣 �솗�씤�븳�떎.
-    private boolean checkIssueModifyPermission(Boolean hasPermission, String checkType, IssueVo issueVo, List<UserVo> issueUserVos) {
+    private boolean checkIssueModifyPermission(Boolean hasPermission, String checkType, IssueVo issueVo, List<UserVo> issueUserVos, List<DepartmentVo> issueDepartmentVos) {
         if (!hasPermission) {
             switch (checkType) {
                 case Issue.WORKSPACE_MANAGER:  //  �뾽臾� 怨듦컙 愿�由ъ옄
@@ -1262,15 +1261,28 @@
                         hasPermission = true;
                         break;
                     }
-
-                    //   �씠�뒋 �떞�떦�옄 �뿬遺� �솗�씤 => �떞�떦遺��꽌濡� �닔�젙 - 泥댄겕
-                    /*for (UserVo issueUserVo : issueUserVos) {
+                    //   �씠�뒋 �떞�떦�옄 �뿬遺� �솗�씤
+                    for (UserVo issueUserVo : issueUserVos) {
                         if (issueUserVo.getId().equals(this.webAppUtil.getLoginId())) {
                             hasPermission = true;
                             break;
                         }
-                    }*/
+                    }
+                    break;
 
+                case Issue.DEPARTMENT:
+                    //  �떞�떦遺��꽌媛� �뾾�쑝硫� 紐⑤뱺 �궗�슜�옄媛� �닔�젙 沅뚰븳�쓣 媛뽯뒗�떎.
+                    if (issueDepartmentVos.size() < 1) {
+                        hasPermission = true;
+                        break;
+                    }
+                    //   �씠�뒋 �떞�떦遺��꽌 �뿬遺� �솗�씤
+                    /*for (DepartmentVo issueDepartmentVo : issueDepartmentVos) {
+                        if (issueDepartmentVo.getId().equals()) {
+                            hasPermission = true;
+                            break;
+                        }
+                    }*/
                     break;
             }
         }
@@ -1373,7 +1385,7 @@
         issue.setProject(this.projectService.getProject(issueForm.getProjectId()));
 
         //  蹂�寃� �씠�젰 �젙蹂� 異붿텧
-        this.issueHistoryService.detectIssueManager(issue, issueForm, detectIssueChange);
+        this.issueHistoryService.detectIssueDepartment(issue, issueForm, detectIssueChange);
 
         //this.issueUserService.modifyIssueUser(issue, issue.getProject().getWorkspace(), issueForm.getUserIds());
         this.issueDepartmentService.modifyIssueDepartment(issue, issue.getProject().getWorkspace(), issueForm.getDepartmentIds());
@@ -1982,6 +1994,7 @@
             Map<String, Long> issueRiskMap = new HashMap<>();
             issueRiskMap.put("issueId", issueForm.getId());
             issueRiskMap.put("changeAssigneeCount", 0L);
+            issueRiskMap.put("changeDepartmentCount", 0L);
             issueRiskMap.put("changeIssueStatusCount", 0L);
             issueRiskMap.put("workspaceId", workspace.getId());
             issueRiskMap.put("issueStatusIds", issueForm.getIssueStatusId());
@@ -2613,16 +2626,30 @@
 
     @Transactional
     @Override
-    public void modifyParentIssue(IssueForm issueForm) {
-        Issue issue = this.issueRepository.getOne(issueForm.getId());
-        Long parentIssueId = issueForm.getParentIssueId();
-        if (parentIssueId != null) {
-            Issue parentIssue = this.issueRepository.getOne(parentIssueId);
+    public void modifyParentIssue(IssueForm issueDownForm) {
+        System.out.println(issueDownForm.getTitle());
+        Issue issue = this.getIssue(issueDownForm.getId());
+        Issue parentIssue = issue.getParentIssue();
+
+        Long newParentIssueId = issueDownForm.getParentIssueId();
+        StringBuilder sb = new StringBuilder();
+
+        IssueHistoryType type =  IssueHistoryType.ADD;
+        if (newParentIssueId != null) {
+           // todo �씠�쟾 �븯�쐞 �씪媛� �엳�뒪�넗由ш린濡� �븘�슂
+            type = IssueHistoryType.ADD;
+            parentIssue = this.getIssue(newParentIssueId);
             issue.setParentIssue(parentIssue);
+            this.issueHistoryService.detectDownIssues(type, issue, sb);
         } else  {
+            // remove
+            type = IssueHistoryType.DELETE;
+            this.issueHistoryService.detectDownIssues(type, issue, sb);
             issue.setParentIssue(null);
         }
 
+        this.issueHistoryService.addIssueHistory(parentIssue, IssueHistoryType.MODIFY, sb.toString());
         this.issueRepository.saveAndFlush(issue);
+
     }
 }
diff --git a/src/main/java/kr/wisestone/owl/service/impl/WidgetServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/WidgetServiceImpl.java
index 799ed53..6e82dd0 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/WidgetServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/WidgetServiceImpl.java
@@ -512,9 +512,11 @@
         widgetCondition.setPage(pageable.getPageNumber() * pageable.getPageSize());
         widgetCondition.setPageSize(pageable.getPageSize());
 
-        Map<String, Object> countChangeStatusAndAssigneeIssue = new HashMap<>();
-        countChangeStatusAndAssigneeIssue.put("changeAssigneeCount", 0L);
-        countChangeStatusAndAssigneeIssue.put("changeIssueStatusCount", 0L);
+        //Map<String, Object> countChangeStatusAndAssigneeIssue = new HashMap<>();
+        //countChangeStatusAndAssigneeIssue.put("changeAssigneeCount", 0L);
+        Map<String, Object> countChangeStatusAndDepartmentIssue = new HashMap<>();
+        countChangeStatusAndDepartmentIssue.put("changeDepartmentCount", 0L);
+        countChangeStatusAndDepartmentIssue.put("changeIssueStatusCount", 0L);
         //  0.212 - 0.213
         List<Map<String, Object>> riskIssues = Lists.newArrayList();
         //  0.244 - 0.248
@@ -522,7 +524,8 @@
         Long totalCount = 0L;
 
         if (widgetCondition.getProjectIds().size() > 0) {
-            countChangeStatusAndAssigneeIssue = this.widgetMapper.countChangeStatusAndAssigneeIssue(widgetCondition);
+            //countChangeStatusAndAssigneeIssue = this.widgetMapper.countChangeStatusAndAssigneeIssue(widgetCondition);
+            countChangeStatusAndDepartmentIssue = this.widgetMapper.countChangeStatusAndDepartmentIssue(widgetCondition);
             riskIssues = this.widgetMapper.findRiskIssue(widgetCondition);
             totalCount = this.widgetMapper.countRiskIssue(widgetCondition);
         }
@@ -535,8 +538,9 @@
         int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1;
         Map<String, Object> results = new HashMap<>();
 
-        results.put("changeAssigneeCount", MapUtil.getLong(countChangeStatusAndAssigneeIssue, "changeAssigneeCount"));
-        results.put("changeIssueStatusCount", MapUtil.getLong(countChangeStatusAndAssigneeIssue, "changeIssueStatusCount"));
+        //results.put("changeAssigneeCount", MapUtil.getLong(countChangeStatusAndAssigneeIssue, "changeAssigneeCount"));
+        results.put("changeDepartmentCount", MapUtil.getLong(countChangeStatusAndDepartmentIssue, "changeDepartmentCount"));
+        results.put("changeIssueStatusCount", MapUtil.getLong(countChangeStatusAndDepartmentIssue, "changeIssueStatusCount"));
         results.put("issues", riskIssues);
         results.put(Constants.REQ_KEY_PAGE_VO, new ResPage(pageable.getPageNumber(), pageable.getPageSize(),
                 totalPage, totalCount));
diff --git a/src/main/resources/migration/V1_11__Alter_Table.sql b/src/main/resources/migration/V1_11__Alter_Table.sql
index f4f4ac6..c455bc7 100644
--- a/src/main/resources/migration/V1_11__Alter_Table.sql
+++ b/src/main/resources/migration/V1_11__Alter_Table.sql
@@ -187,3 +187,6 @@
 ALTER TABLE `issue_table_config` ADD COLUMN  `issue_id` BIGINT(20) NOT NULL;
 ALTER TABLE `issue_table_config` ADD COLUMN  `issue_table_type` INT(11) NOT NULL;
 ALTER TABLE `issue_table_config` ADD INDEX `issueTableTypeIndex`(`issue_table_type`);
+
+-- issue_risk �뀒�씠釉� 遺��꽌蹂�寃� 移댁슫�듃 而щ읆 異붽�
+ALTER TABLE `issue_risk` ADD COLUMN `change_department_count` BIGINT(20) NOT NULL DEFAULT '0';
diff --git a/src/main/resources/mybatis/query-template/issue-template.xml b/src/main/resources/mybatis/query-template/issue-template.xml
index 8f0f1ec..e2a058d 100644
--- a/src/main/resources/mybatis/query-template/issue-template.xml
+++ b/src/main/resources/mybatis/query-template/issue-template.xml
@@ -367,12 +367,12 @@
     <!--    �씠�뒋 由ъ뒪�겕 bulk insert, import �뿉�꽌 �궗�슜 -->
     <insert id="insertIssueRiskBatch" keyColumn="id" keyProperty="id" useGeneratedKeys="true"
             parameterType="java.util.HashMap">
-        INSERT INTO issue_risk(issue_id, workspace_id, change_assignee_count, change_issue_status_count,
+        INSERT INTO issue_risk(issue_id, workspace_id, change_assignee_count, change_department_count, change_issue_status_count,
         issue_status_ids,
         register_id, modify_id, register_date, modify_date)
         VALUES
         <foreach collection="list" item="map" index="index" separator="," open="" close="">
-            (#{map.issueId}, #{map.workspaceId}, #{map.changeAssigneeCount}, #{map.changeIssueStatusCount},
+            (#{map.issueId}, #{map.workspaceId}, #{map.changeAssigneeCount}, #{map.changeDepartmentCount}, #{map.changeIssueStatusCount},
             #{map.issueStatusIds},
             #{map.registerId}, #{map.registerId}, NOW(), NOW())
         </foreach>
diff --git a/src/main/resources/mybatis/query-template/widget-template.xml b/src/main/resources/mybatis/query-template/widget-template.xml
index 3ff9f57..a460ac6 100644
--- a/src/main/resources/mybatis/query-template/widget-template.xml
+++ b/src/main/resources/mybatis/query-template/widget-template.xml
@@ -305,7 +305,7 @@
     <!--    5踰� �쐞�젽 �떆�옉 -->
 
     <!--    踰덈났�릺�뒗 �긽�깭 蹂�寃� 諛� 鍮덈쾲�븳 �떞�떦�옄 蹂�寃� 媛쒖닔   -->
-    <select id="countChangeStatusAndAssigneeIssue" resultType="java.util.HashMap"
+    <!--<select id="countChangeStatusAndAssigneeIssue" resultType="java.util.HashMap"
             parameterType="kr.wisestone.owl.web.condition.WidgetCondition">
         select
         count(case when ir.change_assignee_count > 3 then 1 end) as changeAssigneeCount,
@@ -322,10 +322,29 @@
                 </foreach>
             </when>
         </choose>
+    </select>-->
+
+    <select id="countChangeStatusAndDepartmentIssue" resultType="java.util.HashMap"
+            parameterType="kr.wisestone.owl.web.condition.WidgetCondition">
+        select
+        count(case when ir.change_department_count > 3 then 1 end) as changeDepartmentCount,
+        count(case when ir.change_issue_status_count > 3 then 1 end) as changeIssueStatusCount
+        from issue i
+        inner join issue_risk ir on ir.issue_id = i.id
+        inner join issue_status iss on iss.id = i.issue_status_id
+        where iss.issue_status_type != 'CLOSE'
+        <choose>
+            <when test="projectIds.size != 0">
+                AND i.project_id IN
+                <foreach collection="projectIds" item="item" index="index" separator="," open="(" close=")">
+                    #{item}
+                </foreach>
+            </when>
+        </choose>
     </select>
 
     <!--    �쐞�뿕 愿�由�    -->
-    <select id="findRiskIssue" resultType="java.util.HashMap"
+    <!--<select id="findRiskIssue" resultType="java.util.HashMap"
             parameterType="kr.wisestone.owl.web.condition.WidgetCondition">
         select
         DISTINCT i.id, i.title, iss.name as issueStatusName,
@@ -351,6 +370,33 @@
         <if test="page != null and !page.equals('')">
             limit #{pageSize} offset #{page};
         </if>
+    </select>-->
+    <select id="findRiskIssue" resultType="java.util.HashMap"
+            parameterType="kr.wisestone.owl.web.condition.WidgetCondition">
+        select
+        DISTINCT i.id, i.title, iss.name as issueStatusName,
+        (case when ir.change_department_count > 3 then true else false end) as changeDepartmentType,
+        (case when ir.change_issue_status_count > 3 then true else false end) as changeIssueStatusType,
+        CONCAT(p.project_key, '-', i.issue_number) AS issueKey,
+        i.issue_number as issueNumber,
+        p.project_key as projectKey
+        from issue i
+        inner join issue_risk ir on ir.issue_id = i.id
+        inner join issue_status iss on iss.id = i.issue_status_id
+        inner join project p on p.id = i.project_id
+        where iss.issue_status_type != 'CLOSE'
+        <choose>
+            <when test="projectIds.size != 0">
+                AND p.id IN
+                <foreach collection="projectIds" item="item" index="index" separator="," open="(" close=")">
+                    #{item}
+                </foreach>
+            </when>
+        </choose>
+        and (ir.change_department_count > 3 || ir.change_issue_status_count > 3)
+        <if test="page != null and !page.equals('')">
+            limit #{pageSize} offset #{page};
+        </if>
     </select>
 
     <!--    �쐞�뿕 愿�由� 媛쒖닔    -->
@@ -370,7 +416,7 @@
                 </foreach>
             </when>
         </choose>
-        and (ir.change_assignee_count > 3 || ir.change_issue_status_count > 3)
+        and (ir.change_department_count > 3 || ir.change_issue_status_count > 3)
     </select>
 
     <!--    5踰� �쐞�젽 �걹 -->
diff --git a/src/main/webapp/i18n/ko/global.json b/src/main/webapp/i18n/ko/global.json
index 10bfc0a..7117c04 100644
--- a/src/main/webapp/i18n/ko/global.json
+++ b/src/main/webapp/i18n/ko/global.json
@@ -168,6 +168,33 @@
         "relationIssueRemove" : "�뿰愿� �씠�뒋 �궘�젣",
         "relationIssueRemoveHistory" : "�뿰愿� �씠�뒋媛� �궘�젣�릺�뿀�뒿�땲�떎.",
         "relationIssueAddHistory" : "�뿰愿� �씠�뒋媛� 異붽��릺�뿀�뒿�땲�떎.",
+        "downIssueRemoveHistory" : "�븯�쐞 �씠�뒋媛� �궘�젣�릺�뿀�뒿�땲�떎.",
+        "downIssueAddHistory" : "�븯�쐞 �씠�뒋媛� 異붽��릺�뿀�뒿�땲�떎.",
+
+        "issueCompanyRemoveHistory" : "�뾽泥� �젙蹂닿� �궘�젣�릺�뿀�뒿�땲�떎.",
+        "issueCompanyAddHistory" : "�뾽泥� �젙蹂닿� 異붽��릺�뿀�뒿�땲�떎.",
+        "issueCompanyModifyHistory" : "�뾽泥� �젙蹂닿� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueCompanyModifyManagerHistory" : "�뾽泥� �젙蹂댁쓽 �떞�떦�옄媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueCompanyModifyTelHistory" : "�뾽泥� �젙蹂댁쓽 �쟾�솕踰덊샇媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueCompanyModifyEmailHistory" : "�뾽泥� �젙蹂댁쓽 �씠硫붿씪�씠 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueCompanyModifyMemoHistory" : "�뾽泥� �젙蹂댁쓽 鍮꾧퀬媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+
+        "issueIspRemoveHistory" : "ISP �젙蹂닿� �궘�젣�릺�뿀�뒿�땲�떎.",
+        "issueIspAddHistory" : "ISP �젙蹂닿� 異붽��릺�뿀�뒿�땲�떎.",
+        "issueIspModifyHistory" : "ISP �젙蹂닿� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueIspModifyManagerHistory" : "ISP �젙蹂댁쓽 �떞�떦�옄媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueIspModifyTelHistory" : "ISP �젙蹂댁쓽 �쟾�솕踰덊샇媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueIspModifyEmailHistory" : "ISP �젙蹂댁쓽 �씠硫붿씪�씠 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueIspModifyMemoHistory" : "ISP �젙蹂댁쓽 鍮꾧퀬媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+
+        "issueHostingRemoveHistory" : "�샇�뒪�똿 �젙蹂닿� �궘�젣�릺�뿀�뒿�땲�떎.",
+        "issueHostingAddHistory" : "�샇�뒪�똿 �젙蹂닿� 異붽��릺�뿀�뒿�땲�떎.",
+        "issueHostingModifyHistory" : "�샇�뒪�똿 �젙蹂닿� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueHostingModifyManagerHistory" : "�샇�뒪�똿 �젙蹂댁쓽 �떞�떦�옄媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueHostingModifyTelHistory" : "�샇�뒪�똿 �젙蹂댁쓽 �쟾�솕踰덊샇媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueHostingModifyEmailHistory" : "�샇�뒪�똿 �젙蹂댁쓽 �씠硫붿씪�씠 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "issueHostingModifyMemoHistory" : "�샇�뒪�똿 �젙蹂댁쓽 鍮꾧퀬媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+
         "requireIssueTitle": "�씠�뒋 �젣紐⑹쓣 �엯�젰�븯�꽭�슂.",
         "issueList": "�씠�뒋 紐⑸줉",
         "summaryIssueActivity": "�씠�뒋 �솢�룞 �궡�뿭 �슂�빟",
@@ -755,6 +782,7 @@
         "updatePeriod": "湲곌컙�씠 蹂�寃쎈릺�뿀�뒿�땲�떎.",
         "unspecified": "誘몄��젙",
         "updateAssignee": "�떞�떦�옄媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
+        "updateDepartment": "�떞�떦遺��꽌媛� 蹂�寃쎈릺�뿀�뒿�땲�떎.",
         "none": "�뾾�쓬",
         "updateAttachment": "泥⑤� �뙆�씪�씠 蹂�寃쎈릺�뿀�뒿�땲�떎.",
         "deleteAttachment": "泥⑤� �뙆�씪�씠 �궘�젣�릺�뿀�뒿�땲�떎.",

--
Gitblit v1.8.0