From ee356fead3840ad1e34bee7a15d72fdbc435ecb0 Mon Sep 17 00:00:00 2001
From: jhjang <jhjang@maprex.co.kr>
Date: 수, 08 12월 2021 17:20:13 +0900
Subject: [PATCH] - api 하위 이슈 설정메뉴 수정 - 이슈 유형마다 자동 종료 설정할수있도록 수정 - 기타 오류 수정

---
 src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java      |   18 ++
 src/main/resources/migration/V1_12__Alter_Table.sql                    |    3 
 src/main/resources/mybatis/query-template/issueType-template.xml       |    3 
 src/main/webapp/scripts/components/api/api.service.js                  |    8 +
 src/main/webapp/views/api/apiSettingOverlap.html                       |   45 ++++++
 src/main/java/kr/wisestone/owl/service/IssueTypeService.java           |    2 
 src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java             |    9 +
 src/main/resources/mybatis/query-template/issue-template.xml           |    9 +
 src/main/java/kr/wisestone/owl/mapper/IssueMapper.java                 |    2 
 src/main/java/kr/wisestone/owl/domain/IssueType.java                   |   12 +
 src/main/webapp/scripts/components/utils/autoComplete.controller.js    |   47 ++++++
 src/main/webapp/scripts/app/api/apiSetting.controller.js               |  170 +++++++++++++++++------
 src/main/java/kr/wisestone/owl/vo/IssueTypeVo.java                     |   10 +
 src/main/java/kr/wisestone/owl/web/controller/IssueTypeController.java |   12 +
 src/main/webapp/i18n/ko/global.json                                    |    9 +
 src/main/java/kr/wisestone/owl/web/controller/IssueController.java     |    1 
 src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java  |   50 ++++++-
 src/main/webapp/views/api/apiSetting.html                              |    2 
 18 files changed, 348 insertions(+), 64 deletions(-)

diff --git a/src/main/java/kr/wisestone/owl/domain/IssueType.java b/src/main/java/kr/wisestone/owl/domain/IssueType.java
index b11f875..a9c98ca 100644
--- a/src/main/java/kr/wisestone/owl/domain/IssueType.java
+++ b/src/main/java/kr/wisestone/owl/domain/IssueType.java
@@ -35,6 +35,10 @@
     @JoinColumn(name = "project_id")
     private Project project;
 
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "complete_issue_status_id")
+    private IssueStatus issueStatus;
+
     /*@ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "company_id")
     private CompanyField companyField;
@@ -132,4 +136,12 @@
     public void setUsePartner(Long usePartner) {
         this.usePartner = usePartner;
     }
+
+    public IssueStatus getIssueStatus() {
+        return issueStatus;
+    }
+
+    public void setIssueStatus(IssueStatus issueStatus) {
+        this.issueStatus = issueStatus;
+    }
 }
diff --git a/src/main/java/kr/wisestone/owl/mapper/IssueMapper.java b/src/main/java/kr/wisestone/owl/mapper/IssueMapper.java
index 5c6f7e8..90bbfc6 100644
--- a/src/main/java/kr/wisestone/owl/mapper/IssueMapper.java
+++ b/src/main/java/kr/wisestone/owl/mapper/IssueMapper.java
@@ -50,5 +50,7 @@
     Long countByIssueTypeIdAndDate(IssueTypeCondition issueTypeCondition);
 
     Long countByDepartment(IssueCondition issueCondition);
+
+    List<Map<String, Object>> findNotCompleteByParentIssueId(Long parentIssueId);
 }
 
diff --git a/src/main/java/kr/wisestone/owl/service/IssueTypeService.java b/src/main/java/kr/wisestone/owl/service/IssueTypeService.java
index 30a03d5..4bcfbe0 100644
--- a/src/main/java/kr/wisestone/owl/service/IssueTypeService.java
+++ b/src/main/java/kr/wisestone/owl/service/IssueTypeService.java
@@ -31,6 +31,8 @@
 
     IssueType modifyIssueType(IssueTypeForm issueTypeForm);
 
+    IssueType modifyIssueTypeCompleteIssueStatus(IssueTypeForm issueTypeForm);
+
     IssueType getIssueType(Long id);
 
     void removeIssueTypes(IssueTypeForm issueTypeForm);
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 290fc31..2e0a09a 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -1509,13 +1509,21 @@
     }
 
 
+    // �븯�쐞 �씠�뒋媛� 紐⑤몢 醫낅즺 泥섎━ �릺�뿀�쓣 寃쎌슦 �긽�쐞�씠�뒋�룄 �셿猷� 泥섎━
+    private void setParentIssueComplete(Issue parentIssue) {
+        if (parentIssue != null) {
+            this.issueMapper.findNotCompleteByParentIssueId(parentIssue.getId());
+
+        }
+    }
+
+
     // �씠�뒋瑜� �닔�젙�븳�떎(api�슜)
     @Override
     @Transactional
     public List<Issue> modifyIssue(IssueApiForm issueApiForm, List<MultipartFile> files) {
         User user = this.convertToUser(issueApiForm.getToken());
         IssueForm issueForm = this.convertToIssueForm(issueApiForm, user);
-
 
         List<IssueVo> issueVos = this.findIssue(issueApiForm);
         if (issueVos != null && issueVos.size() > 0) {
@@ -1527,7 +1535,13 @@
                 } else {
                     issueForm.setId(issueVo.getId());
                 }
-                issue.add(this.modifyIssueForApi(user, issueForm, files));
+                Issue modifyIssue = this.modifyIssueForApi(user, issueForm, files);
+                Issue parentIssue = modifyIssue.getParentIssue();
+                if (parentIssue != null) {
+                    List<Map<String, Object>> results = this.issueMapper.findNotCompleteByParentIssueId(parentIssue.getId());
+                }
+
+                issue.add(modifyIssue);
             }
             return issue;
         } else {
diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java
index a9ce5db..1ffff50 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java
@@ -51,13 +51,7 @@
     private WorkspaceService workspaceService;
 
     @Autowired
-    private CompanyFieldService companyFieldService;
-
-    @Autowired
-    private IspFieldService ispFieldService;
-
-    @Autowired
-    private HostingFieldService hostingFieldService;
+    private IssueStatusService issueStatusService;
 
     @Autowired
     private IssueTypeMapper issueTypeMapper;
@@ -182,12 +176,22 @@
                 Project project = this.projectService.getProject(projectId);
                 ProjectVo projectVo = ConvertUtil.copyProperties(project, ProjectVo.class);
                 result.put("projectVo", projectVo);
+
+            }
+            Long issueStatusId = MapUtil.getLong(result, "completeIssueStatusId");
+            if (issueStatusId != null) {
+                IssueStatus issueStatus = this.issueStatusService.getIssueStatus(issueStatusId);
+                IssueStatusVo issueStatusVo = ConvertUtil.copyProperties(issueStatus, IssueStatusVo.class);
+                result.put("completeIssueStatusVo", issueStatusVo);
             }
         }
 
         Long totalCount = this.issueTypeMapper.count(condition);
         int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1;
         List<IssueTypeVo> issueTypeVos = ConvertUtil.convertListToListClass(results, IssueTypeVo.class);
+//        for (IssueTypeVo issueTypeVo : issueTypeVos) {
+//
+//        }
 
         //  �씠�뒋 �쑀�삎�뿉 �뿰寃곕맂 �썙�겕�뵆濡쒖슦 �젙蹂대�� �뀑�똿�븳�떎.
         if (condition.getDeep() != null) {
@@ -195,6 +199,7 @@
         }
 
         this.setUseIssueTypeByProject(issueTypeVos);
+        this.setUseIssueTypeByIssueStatus(issueTypeVos);
         /*this.setUseIssueTypeByCompanyField(issueTypeVos);
         this.setUseIssueTypeByIspField(issueTypeVos);
         this.setUseIssueTypeByHostingField(issueTypeVos);*/
@@ -232,6 +237,17 @@
             Project project = issueType.getProject();
             if (project != null) {
                 issueTypeVo.setProjectVo(ConvertUtil.copyProperties(issueType.getProject(), ProjectVo.class));
+            }
+        }
+    }
+
+    private void setUseIssueTypeByIssueStatus(List<IssueTypeVo> issueTypeVos) {
+        for (IssueTypeVo issueTypeVo : issueTypeVos) {
+            IssueType issueType = this.getIssueType(issueTypeVo.getId());
+
+            IssueStatus issueStatus = issueType.getIssueStatus();
+            if (issueStatus != null) {
+                issueTypeVo.setCompleteIssueStatusVo(ConvertUtil.copyProperties(issueType.getIssueStatus(), IssueStatusVo.class));
             }
         }
     }
@@ -284,6 +300,26 @@
         resJsonData.put(Constants.RES_KEY_CONTENTS, issueTypeVo);
     }
 
+    // �씠�뒋 �쑀�삎�쓣 �닔�젙�븳�떎. �옄�룞 醫낅즺 �꽕�젙留� �닔�젙
+    @Override
+    @Transactional
+    public IssueType modifyIssueTypeCompleteIssueStatus(IssueTypeForm issueTypeForm) {
+        //  �궗�슜�븯怨� �엳�뒗 �뾽臾� 怨듦컙�씠 �솢�꽦 �긽�깭�씤吏� �솗�씤�븳�떎. �궗�슜 怨듦컙�뿉�꽌 濡쒓렇�씤�븳 �궗�슜�옄媛� 鍮꾪솢�꽦�씤吏� �솗�씤�븳�떎.
+        this.workspaceService.checkUseWorkspace();
+
+        IssueType issueType = this.getIssueType(issueTypeForm.getId());
+        if (issueTypeForm.getCompleteIssueStatusId() != null) {
+            // api�뿉�꽌 �궗�슜�븯�뒗 �옄�룞 醫낅즺 �씠�뒋 �긽�깭
+            IssueStatus issueStatus = this.issueStatusService.getIssueStatus(issueTypeForm.getCompleteIssueStatusId());
+            issueType.setIssueStatus(issueStatus);
+        }else {
+            issueType.setIssueStatus(null);
+        }
+
+        this.issueTypeRepository.saveAndFlush(issueType);
+        return issueType;
+    }
+
     //  �씠�뒋 �쑀�삎�쓣 �닔�젙�븳�떎.
     @Override
     @Transactional
diff --git a/src/main/java/kr/wisestone/owl/vo/IssueTypeVo.java b/src/main/java/kr/wisestone/owl/vo/IssueTypeVo.java
index 0ce164c..94a8ab7 100644
--- a/src/main/java/kr/wisestone/owl/vo/IssueTypeVo.java
+++ b/src/main/java/kr/wisestone/owl/vo/IssueTypeVo.java
@@ -1,5 +1,6 @@
 package kr.wisestone.owl.vo;
 
+import com.amazonaws.services.elastictranscoder.model.ReadPipelineRequest;
 import com.google.common.collect.Lists;
 
 import java.util.List;
@@ -14,6 +15,7 @@
     private String color;
     private WorkflowVo workflowVo;
     private ProjectVo projectVo;
+    private IssueStatusVo completeIssueStatusVo;
 
     private List<UsePartnerVo> usePartnerVos = Lists.newArrayList();
 
@@ -84,4 +86,12 @@
     public void setUsePartnerVos(List<UsePartnerVo> usePartnerVos) {
         this.usePartnerVos = usePartnerVos;
     }
+
+    public IssueStatusVo getCompleteIssueStatusVo() {
+        return completeIssueStatusVo;
+    }
+
+    public void setCompleteIssueStatusVo(IssueStatusVo completeIssueStatusVo) {
+        this.completeIssueStatusVo = completeIssueStatusVo;
+    }
 }
diff --git a/src/main/java/kr/wisestone/owl/web/controller/IssueController.java b/src/main/java/kr/wisestone/owl/web/controller/IssueController.java
index 8a3f3e5..f752960 100644
--- a/src/main/java/kr/wisestone/owl/web/controller/IssueController.java
+++ b/src/main/java/kr/wisestone/owl/web/controller/IssueController.java
@@ -199,5 +199,4 @@
         this.issueService.findApiIssue(ApiMonitorCondition.make(params.get(Constants.REQ_KEY_CONTENT)), resJsonData);
         return this.setSuccessMessage(resJsonData);
     }
-
 }
diff --git a/src/main/java/kr/wisestone/owl/web/controller/IssueTypeController.java b/src/main/java/kr/wisestone/owl/web/controller/IssueTypeController.java
index a58371e..de996ab 100644
--- a/src/main/java/kr/wisestone/owl/web/controller/IssueTypeController.java
+++ b/src/main/java/kr/wisestone/owl/web/controller/IssueTypeController.java
@@ -2,6 +2,7 @@
 
 import kr.wisestone.owl.constant.Constants;
 import kr.wisestone.owl.service.IssueTypeService;
+import kr.wisestone.owl.web.condition.ApiMonitorCondition;
 import kr.wisestone.owl.web.condition.IssueTypeCondition;
 import kr.wisestone.owl.web.form.IssueTypeForm;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -93,4 +94,15 @@
     public ModelAndView downloadExcel(HttpServletRequest request, Model model) {
         return this.issueTypeService.downloadExcel(request, model);
     }
+
+    //  api �옄�룞 醫낅즺 �씠�뒋�긽�깭 �꽕�젙
+    @RequestMapping(value = "/api/saveCompleteIssueStatus", produces = MediaType.APPLICATION_JSON_VALUE)
+    public
+    @ResponseBody
+    Map<String, Object> saveCompleteIssueStatus(@RequestBody Map<String, Map<String, Object>> params) {
+        Map<String, Object> resJsonData = new HashMap<>();
+        IssueTypeForm issueTypeForm = IssueTypeForm.make(params.get(Constants.REQ_KEY_CONTENT));
+        this.issueTypeService.modifyIssueTypeCompleteIssueStatus(issueTypeForm);
+        return this.setSuccessMessage(resJsonData);
+    }
  }
diff --git a/src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java b/src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java
index 039f3d9..0aa73e3 100644
--- a/src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java
+++ b/src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java
@@ -18,6 +18,7 @@
     private String color;
     private Long workflowId;
     private Long projectId;
+    private Long completeIssueStatusId;
     private List<Long> removeIds = Lists.newArrayList();
     private Long usePartner;
 
@@ -114,4 +115,12 @@
     public void setUsePartner(Long usePartner) {
         this.usePartner = usePartner;
     }
+
+    public Long getCompleteIssueStatusId() {
+        return completeIssueStatusId;
+    }
+
+    public void setCompleteIssueStatusId(Long completeIssueStatusId) {
+        this.completeIssueStatusId = completeIssueStatusId;
+    }
 }
diff --git a/src/main/resources/migration/V1_12__Alter_Table.sql b/src/main/resources/migration/V1_12__Alter_Table.sql
index cbce5f8..8076925 100644
--- a/src/main/resources/migration/V1_12__Alter_Table.sql
+++ b/src/main/resources/migration/V1_12__Alter_Table.sql
@@ -5,3 +5,6 @@
 ALTER TABLE `company_field` ADD COLUMN  `url` VARCHAR(255) NULL;
 ALTER TABLE `isp_field` ADD COLUMN  `url` VARCHAR(255) NULL;
 ALTER TABLE `hosting_field` ADD COLUMN  `url` VARCHAR(255) NULL;
+
+-- �옄�룞 �셿猷� �긽�깭 異붽�
+ALTER TABLE `issue_type` ADD COLUMN  `complete_issue_status_id` BIGINT(20) NULL;
\ No newline at end of file
diff --git a/src/main/resources/mybatis/query-template/issue-template.xml b/src/main/resources/mybatis/query-template/issue-template.xml
index 980a1ed..b44cb34 100644
--- a/src/main/resources/mybatis/query-template/issue-template.xml
+++ b/src/main/resources/mybatis/query-template/issue-template.xml
@@ -975,4 +975,13 @@
         </choose>
     </select>
 
+    <!--  醫낅즺 �븞�맂 �븯�쐞 �씠�뒋 媛��졇�삤湲� -->
+    <select id="findNotCompleteByParentIssueId" resultType="java.util.HashMap" parameterType="java.lang.Long">
+        SELECT
+        iss.id as id
+        FROM issue iss
+        INNER JOIN issue_status issueStatus on iss.issue_status_id = issueStatus.id
+        WHERE iss.parent_issue_id = #{parentIssueId}
+        AND issueStatus.issue_status_type != 'CLOSE'
+    </select>
 </mapper>
diff --git a/src/main/resources/mybatis/query-template/issueType-template.xml b/src/main/resources/mybatis/query-template/issueType-template.xml
index 4aacf92..b26e4d5 100644
--- a/src/main/resources/mybatis/query-template/issueType-template.xml
+++ b/src/main/resources/mybatis/query-template/issueType-template.xml
@@ -9,7 +9,8 @@
         it.name as name,
         it.description as description,
         it.color as color,
-        it.project_id as projectId
+        it.project_id as projectId,
+        it.complete_issue_status_id as completeIssueStatusId
         FROM
         issue_type it
         INNER JOIN workspace ws on it.workspace_id = ws.id
diff --git a/src/main/webapp/i18n/ko/global.json b/src/main/webapp/i18n/ko/global.json
index 6c33199..b0a9ea3 100644
--- a/src/main/webapp/i18n/ko/global.json
+++ b/src/main/webapp/i18n/ko/global.json
@@ -870,7 +870,7 @@
         "create" : "�넗�겙 �깮�꽦",
         "example" : "�궗�슜 �삁�떆",
         "columnSetting" : "湲곕낯媛� �꽕�젙",
-        "overlapSetting" : "以묐났 �븘�뱶 �꽕�젙",
+        "overlapSetting" : "�븯�쐞 �씠�뒋 �꽕�젙",
         "addOverlapField" : "以묐났 �븘�뱶 異붽�",
         "failedToApiTokenFind" : "API �넗�겙 議고쉶 �떎�뙣",
         "failedToApiTokenRemove" : "API �넗�겙 �궘�젣 �떎�뙣",
@@ -885,7 +885,12 @@
         "failedToApiMonitor": "API 湲곕줉 議고쉶 �떎�뙣",
         "requestSample": "API �슂泥� �깦�뵆",
         "requestSampleAdd": "�씠�뒋 異붽�",
-        "requestSampleModify": "�씠�뒋 �닔�젙"
+        "requestSampleModify": "�씠�뒋 �닔�젙",
+        "downIssueOverlapSetting" : "�븯�쐞 �씠�뒋 泥섎━ 湲곗� �빆紐�",
+        "upIssueCompleteIssueStatus" : "�긽�쐞 �씠�뒋 �옄�룞醫낅즺 �씠�뒋 �긽�깭 �꽕�젙",
+        "autoCompleteIssueStatus" : "�옄�룞 醫낅즺 �꽕�젙�븷 �씠�뒋 �긽�깭",
+        "successToApiAutoCompleteIssueStatus" : "�옄�룞 醫낅즺 �씠�뒋 �긽�깭 �꽕�젙 �셿猷�",
+        "failedToApiAutoCompleteIssueStatus" : "�옄�룞 醫낅즺 �씠�뒋 �긽�깭 �꽕�젙 �떎�뙣"
     },
     "companyField" : {
         "info": "�뾽泥댁젙蹂�",
diff --git a/src/main/webapp/scripts/app/api/apiSetting.controller.js b/src/main/webapp/scripts/app/api/apiSetting.controller.js
index 8b88ca9..fc6730e 100644
--- a/src/main/webapp/scripts/app/api/apiSetting.controller.js
+++ b/src/main/webapp/scripts/app/api/apiSetting.controller.js
@@ -23,7 +23,7 @@
                     initForm : initForm,
                     getPriorities : getPriorities,
                     getSeverities : getSeverities,
-                    start : start,
+                    onChangeColumnSetting : onChangeColumnSetting,
                     getIssueTypes : getIssueTypes,
                     onChangeIssueType : onChangeIssueType,
                     reset : reset,
@@ -34,19 +34,22 @@
                     onChangeIssueTypeOverlap : onChangeIssueTypeOverlap,
                     getIssueTypeCustomFields : getIssueTypeCustomFields,
                     getCurrentIssueTypeVo : getCurrentIssueTypeVo,
-                    loadSpec : loadSpec,
                     getIssueStatuses : getIssueStatuses,
                     onChangeIssueTypeSpec : onChangeIssueTypeSpec,
                     createRequestModifyJson : createRequestModifyJson,
                     createRequestAddJson : createRequestAddJson,
                     createCustomFields : createCustomFields,
-                    getProjectList : getProjectList
+                    getProjects : getProjects,
+                    formSubmitCompleteIssueStatus : formSubmitCompleteIssueStatus,
+                    loadPage : loadPage,
+                    resetCompleteIssueStatus : resetCompleteIssueStatus
                 };
 
                 $scope.vm = {
-                    tab : "API_COL_SETTING",
+                    tab : "",
                     issueTypes : [],
                     issueStatuses : [],
+                    completeIssueStatuses : [],
                     severities : [],
                     priorities : [],
                     projects : [],
@@ -76,6 +79,7 @@
                         //     totalPage : 0
                         // }
                     },
+                    completeIssueStatusId : "",
                     issueTypeId : "",
                     issueTypeName : "",
 
@@ -87,6 +91,8 @@
                     projectId : "",
                     projectName : "",
                 };
+
+                angular.extend(this, $controller('autoCompleteController', {$scope : $scope, $injector : $injector}));
 
                 function initForm() {
                     $scope.vm.form.issueApiDefault.title = "";
@@ -100,6 +106,12 @@
                     $scope.fn.formSubmit();
                 }
 
+                // �옄�룞醫낅즺 �꽕�젙 珥덇린�솕
+                function resetCompleteIssueStatus() {
+                    $scope.vm.completeIssueStatusId = "";
+                }
+
+                // �븯�쐞 �씠�뒋 泥섎━ 湲곗� �빆紐� 珥덇린�솕(以묐났泥섎━�븷 �빆紐�)
                 function resetOverlap() {
                     $scope.vm.form.customFieldIds = [];
                     $scope.fn.form.formSubmitOverlap();
@@ -113,11 +125,10 @@
                     Api.findApiOverlap($resourceProvider.getContent(
                         conditions, $resourceProvider.getPageContent(0, 1000))).then(function (result) {
                         if (result.data.message.status === "success") {
-
-                            let customFieldApiOverlaps = result.data.data;
                             $scope.vm.form.customFields = [];
+                            let customFieldApiOverlaps = result.data.data;
 
-                            if (customFieldApiOverlaps != null) {
+                            if (customFieldApiOverlaps != null && customFieldApiOverlaps.length > 0) {
                                 customFieldApiOverlaps.forEach(function (customFieldApiOverlap) {
                                     $scope.vm.form.customFields.push(customFieldApiOverlap.customFieldVo);
                                 });
@@ -129,6 +140,12 @@
                     });
                 }
 
+                $scope.$watch("vm.issueTypeId", function (newValue){
+                    if (newValue != null && newValue !== "") {
+                        $scope.fn.loadPage();
+                    }
+                });
+
                 function getIssueTypes() {
                     var conditions = {
                     };
@@ -138,12 +155,19 @@
                         if (result.data.message.status === "success") {
                             $scope.vm.issueTypes = result.data.data;
                             if ($scope.vm.issueTypes != null && $scope.vm.issueTypes.length > 0) {
-                                $scope.vm.issueTypeId = $scope.vm.issueTypes[0].id.toString();
-                                if ($scope.vm.tab === "API_COL_SETTING") {
-                                    $scope.fn.onChangeIssueType();
-                                } else if ($scope.vm.tab === "API_SPEC_SETTING") {
-                                    $scope.fn.onChangeIssueTypeSpec();
+                                if ($scope.vm.issueTypeId === "") {
+                                    $scope.vm.issueTypeId = $scope.vm.issueTypes[0].id.toString();
                                 }
+                                if ($scope.vm.tab === "") {
+                                    $scope.fn.changeTab("API_COL_SETTING");
+                                }
+
+                                // if ($scope.vm.tab === "API_COL_SETTING") {
+                                //     $scope.fn.onChangeIssueType();
+                                // } else if ($scope.vm.tab === "API_SPEC_SETTING") {
+                                //     $scope.fn.onChangeIssueTypeSpec();
+                                // } else if ($scope.vm.tab === "API_OVERLAP_SETTING") {
+                                // }
                             }
                         }
                         else {
@@ -165,6 +189,8 @@
                 }
 
                 function onChangeIssueTypeOverlap() {
+                    $scope.fn.getIssueStatuses();
+                    $scope.fn.getIssueTypeCustomFields();
                     $scope.fn.getOverlapList();
                 }
 
@@ -177,7 +203,6 @@
                         Api.findApiDefault($resourceProvider.getContent(
                             conditions, $resourceProvider.getPageContent(0, 1000))).then(function (result) {
                             $scope.fn.initForm();
-                            $scope.fn.getIssueTypeCustomFields();
 
                             if (result.data.message.status === "success") {
                                 if (angular.isDefined(result.data.data)) {
@@ -197,6 +222,28 @@
                         });
                     }
 
+                }
+
+                function formSubmitCompleteIssueStatus() {
+                    if ($scope.vm.issueTypeId != null) {
+                        let content = {
+                            id: $scope.vm.issueTypeId,
+                            completeIssueStatusId: $scope.vm.completeIssueStatusId
+                        }
+
+                        Api.saveCompleteIssueStatus($resourceProvider.getContent(
+                            content, $resourceProvider.getPageContent(0, 1000))).then(function (result) {
+
+                            if (result.data.message.status === "success") {
+                                SweetAlert.swal($filter("translate")("api.successToApiAutoCompleteIssueStatus"), result.data.message.message, "success"); // "�꽕�젙 �꽦怨�"
+                                $scope.fn.getIssueTypes();
+                                $scope.fn.getIssueStatuses();
+                                $scope.fn.getIssueTypeCustomFields();
+                            } else {
+                                SweetAlert.swal($filter("translate")("api.failedToApiAutoCompleteIssueStatus"), result.data.message.message, "error"); // "�꽕�젙 �떎�뙣"
+                            }
+                        });
+                    }
                 }
 
                 //  �뤌 泥댄겕
@@ -290,17 +337,18 @@
                     });
                 }
 
-                //  �씠�뒋 �쑀�삎�뿉 �뿰寃곕맂 �궗�슜�옄 �젙�쓽 �븘�뱶
+                     //  �씠�뒋 �쑀�삎�뿉 �뿰寃곕맂 �궗�슜�옄 �젙�쓽 �븘�뱶
                 function getIssueTypeCustomFields() {
 
                     $scope.vm.form.issueCustomFields = [];
 
                     var issueTypeVo = $scope.fn.getCurrentIssueTypeVo();
+                    var projectId = $scope.vm.projectId;
 
-                    if (issueTypeVo == null) return;
+                    if (issueTypeVo == null || projectId == null) return;
 
                     IssueTypeCustomField.find($resourceProvider.getContent({
-                            projectId : $scope.vm.projectId,
+                            projectId : projectId,
                             IssueTypeId : issueTypeVo.id },
                         $resourceProvider.getPageContent(0, 1000))).then(function (result) {
                         $scope.vm.form.issueCustomFields = [];
@@ -321,6 +369,7 @@
                 }
 
 
+
                 //  以묒슂�룄 紐⑸줉
                 function getSeverities() {
                     Severity.find($resourceProvider.getContent({},
@@ -335,19 +384,6 @@
                     });
                 }
 
-                $rootScope.$on("changeColumnSettingTab", function (event, args){
-                    $scope.fn.start();
-                });
-
-
-                $rootScope.$on("changeOverlapSettingTab", function (event, args){
-                    $scope.fn.getOverlapList();
-                });
-
-                $rootScope.$on("changeSpecSettingTab", function (event, args){
-                    $scope.fn.loadSpec();
-                });
-
                 $scope.$on("getIssueTypeListComplete", function (event, args) {
                     if ($scope.vm.tab === "API_SPEC_SETTING") {
                         $scope.fn.createRequestAddJson();
@@ -357,15 +393,44 @@
 
                 function changeTab(tab) {
                     $scope.vm.tab = tab;
+                    $scope.fn.loadPage();
+                }
+
+                // �쁽�옱 �꺆 �럹�씠吏� 遺덈윭�삤湲�
+                function loadPage() {
+                    let tab = $scope.vm.tab;
 
                     if (tab === "API_COL_SETTING") {
-                        $rootScope.$broadcast("changeColumnSettingTab");
+                        $scope.fn.onChangeColumnSetting();
                     } else if (tab === "API_OVERLAP_SETTING") {
-                        $rootScope.$broadcast("changeOverlapSettingTab");
+                        $scope.fn.onChangeIssueTypeOverlap();
                     } else if (tab === "API_SPEC_SETTING") {
-                        $rootScope.$broadcast("changeSpecSettingTab");
+                        $scope.fn.onChangeIssueTypeSpec();
                     }
                 }
+
+                $scope.$on("getIssueStatusComplete", function (event, args){
+                    if ($scope.vm.issueStatuses != null) {
+                        $scope.vm.completeIssueStatuses = [];
+
+                        $scope.vm.issueStatuses.forEach(function (issueStatus) {
+                            if (issueStatus.issueStatusType === "CLOSE") {
+                                $scope.vm.completeIssueStatuses.push(issueStatus);
+                            }
+                        });
+
+                        // �꽕�젙�맂 �긽�깭 吏��젙
+                        $scope.vm.completeIssueStatusId = "";
+                        let issueTypeVo = $scope.fn.getCurrentIssueTypeVo();
+                        if (issueTypeVo.completeIssueStatusVo != null) {
+                            $scope.vm.completeIssueStatuses.forEach(function (issueStatus) {
+                                if (issueStatus.id === issueTypeVo.completeIssueStatusVo.id) {
+                                    $scope.vm.completeIssueStatusId = issueStatus.id.toString();
+                                }
+                            });
+                        }
+                    }
+                });
 
                 function getIssueStatuses() {
                     var condition = {
@@ -376,15 +441,24 @@
 
                         if (result.data.message.status === "success") {
                             $scope.vm.issueStatuses = result.data.data;
+                            $scope.vm.issueStatusId = "";
                             if ($scope.vm.issueStatuses != null && $scope.vm.issueStatuses.length > 0) {
                                 $scope.vm.issueStatusId = $scope.vm.issueStatuses[0].id.toString();
                             }
+                            $scope.$broadcast("getIssueStatusComplete", $scope.vm.issueStatuses);
                         }
                         else {
                             SweetAlert.swal($filter("translate")("issue.failedToCriticalListLookup"), result.data.message.message, "error"); // 以묒슂�룄 紐⑸줉 議고쉶 �떎�뙣
                         }
                     });
                 }
+
+                function onChangeColumnSetting() {
+                    $scope.fn.getSeverities();
+                    $scope.fn.getPriorities();
+                    $scope.fn.onChangeIssueType();
+                }
+
 
                 function onChangeIssueTypeSpec() {
                     $scope.fn.getIssueTypeCustomFields();
@@ -432,7 +506,18 @@
                     $scope.vm.sampleJsonModify = JSON.stringify(jsonData, undefined, 2);
                 }
 
-                function getProjectList() {
+                $scope.$watch(function() {
+                    return $rootScope.projects;
+                }, function() {
+                    if ($rootScope.projects != null && $rootScope.projects.length > 0) {
+                        // 怨듯넻 �뜲�씠�꽣 遺덈윭�삤湲�
+                        $scope.fn.getProjects();
+                        $scope.fn.getIssueTypes();
+                    }
+                }, true);
+
+
+                function getProjects() {
                     if ($rootScope.projects != null) {
                         $scope.vm.projects = [];
                         $rootScope.projects.forEach(function (project){
@@ -440,24 +525,13 @@
                                 $scope.vm.projects.push(project);
                             }
                         });
-                        $scope.vm.projectId = $scope.vm.projects[0].id.toString();
+
+                        if ( $scope.vm.projects.length > 0) {
+                            $scope.vm.projectId = $scope.vm.projects[0].id.toString();
+                        }
                     }
                 }
 
-
-                function loadSpec() {
-                    $scope.fn.getIssueStatuses();
-                    $scope.fn.getIssueTypeCustomFields();
-                }
-
-                function start() {
-                    $scope.fn.initForm();
-                    $scope.fn.getProjectList();
-                    $scope.fn.getSeverities();
-                    $scope.fn.getPriorities();
-                    $scope.fn.getIssueTypes();
-                }
-                $scope.fn.start();
 
             }]);
     });
diff --git a/src/main/webapp/scripts/components/api/api.service.js b/src/main/webapp/scripts/components/api/api.service.js
index 11382e0..d81b9cf 100644
--- a/src/main/webapp/scripts/components/api/api.service.js
+++ b/src/main/webapp/scripts/components/api/api.service.js
@@ -52,7 +52,13 @@
                     $log.debug("API �씠�뒋 �벑濡� 湲곕줉 議고쉶 寃곌낵 : ", response);
                     return response;
                 });
-            }
+            },
+            saveCompleteIssueStatus : function (conditions) {
+                return $http.post("api/saveCompleteIssueStatus", conditions).then(function (response) {
+                    $log.debug("API �씠�뒋 �벑濡� 湲곕줉 議고쉶 寃곌낵 : ", response);
+                    return response;
+                });
+            },
         }
     }
     ]);
diff --git a/src/main/webapp/scripts/components/utils/autoComplete.controller.js b/src/main/webapp/scripts/components/utils/autoComplete.controller.js
index d40a45f..8e9cbc3 100644
--- a/src/main/webapp/scripts/components/utils/autoComplete.controller.js
+++ b/src/main/webapp/scripts/components/utils/autoComplete.controller.js
@@ -23,6 +23,7 @@
                 var IspField = $injector.get("IspField");
                 var HostingField = $injector.get("HostingField");
                 var IssueType = $injector.get("IssueType");
+                var IssueTypeCustomField = $injector.get("IssueTypeCustomField");
                 var CustomField = $injector.get("CustomField");
                 var $log = $injector.get("$log");
                 var SweetAlert = $injector.get("SweetAlert");
@@ -42,6 +43,7 @@
                 $scope.fn.getIssueTypeList = getIssueTypeList;          // �씠�뒋 �쑀�삎 紐⑸줉 議고쉶
                 $scope.fn.getCustomFieldList = getCustomFieldList;          // �궗�슜�옄 �젙�쓽 �븘�뱶 紐⑸줉 議고쉶
                 $scope.fn.getMailTargetAll = getMailTargetAll;          // �궗�슜�옄 �젙�쓽 �븘�뱶 紐⑸줉 議고쉶
+                $scope.fn.getIssueTypeCustomFieldList = getIssueTypeCustomFieldList;      // �씠�뒋 �쑀�삎�뿉�꽌 �궗�슜以묒씤 �궗�슜�옄�젙�쓽 �븘�뱶媛��졇�삤湲�
 
                 function getUserList(query, excludeList, page, callBack) {
                     var conditions = {
@@ -534,6 +536,51 @@
                     return deferred.promise;
                 }
 
+                //  �씠�뒋 �쑀�삎�뿉 �뿰寃곕맂 �궗�슜�옄 �젙�쓽 �븘�뱶
+                function getIssueTypeCustomFieldList(query, excludeList, projectId, issueTypeId, page, callBack) {
+
+                    if (projectId == null) return;
+                    if (issueTypeId == null) return;
+
+                    var deferred = $q.defer();
+
+                    IssueTypeCustomField.find($resourceProvider.getContent({
+                            name : query,
+                            projectId : projectId,
+                            issueTypeId : issueTypeId,
+                            excludeIds : (function () {
+                                var excludeIds = [];
+
+                                angular.forEach(excludeList, function (exclude) {
+                                    excludeIds.push(exclude.id);
+                                });
+
+                                return excludeIds;
+                            })()
+                        },
+                        $resourceProvider.getPageContent(0, 1000))).then(function (result) {
+                        if (result.data.message.status === "success") {
+                            if ($rootScope.isDefined(callBack)) {
+                                callBack(result);
+                            }
+
+                            var customFields = result.data.data;
+                            var customFieldVos = [];
+                            customFields.forEach(function (customField) {
+                                customFieldVos.push(customField.customFieldVo);
+                            })
+
+                            deferred.resolve(customFieldVos);
+                        }
+                        else {
+                            SweetAlert.swal($filter("translate")("issue.failedToUserDefinedFieldListAssociatedLookup"), result.data.message.message, "error"); // �씠�뒋 �쑀�삎�뿉 �뿰寃곕맂 �궗�슜�옄 �젙�쓽 �븘�뱶 紐⑸줉 議고쉶 �떎�뙣
+                        }
+
+                    });
+
+                    return deferred.promise;
+                }
+
                 function getMailTargetAll(excludeList) {
                     var deferred = $q.defer();
 
diff --git a/src/main/webapp/views/api/apiSetting.html b/src/main/webapp/views/api/apiSetting.html
index 350fe93..1be9f02 100644
--- a/src/main/webapp/views/api/apiSetting.html
+++ b/src/main/webapp/views/api/apiSetting.html
@@ -40,7 +40,7 @@
                 <div ng-show="vm.tab == 'API_OVERLAP_SETTING'">
                     <div ng-include include-replace src="'views/api/apiSettingOverlap.html'"></div>
                 </div>
-            </div>
+              </div>
         </div>
     </div>
 </div>
diff --git a/src/main/webapp/views/api/apiSettingOverlap.html b/src/main/webapp/views/api/apiSettingOverlap.html
index 6d0cc83..6d83e51 100644
--- a/src/main/webapp/views/api/apiSettingOverlap.html
+++ b/src/main/webapp/views/api/apiSettingOverlap.html
@@ -47,6 +47,48 @@
 
 </div>
 
+<label for="issueTypeForm" class="issue-label">
+    <span translate="api.upIssueCompleteIssueStatus">�긽�쐞 �씠�뒋 �옄�룞醫낅즺 �씠�뒋 �긽�깭 �꽕�젙</span>
+</label>
+<div class="element-box">
+    <div class="row">
+        <!-- �씠�뒋 �긽�깭 -->
+        <div class="form-group mb10">
+            <label for="issueStatusForm" class="issue-label">
+                <span translate="api.autoCompleteIssueStatus">�씠�뒋 �긽�깭</span>
+            </label>
+            <select id="issueStatusForm"
+                    name="issueStatus"
+                    class="form-control input-sm issue-select-label"
+                    ng-style="{ 'color' : fn.getOptionColor(vm.completeIssueStatuses, vm.completeIssueStatusId) }"
+                    ng-model="vm.completeIssueStatusId"
+                    ng-change="fn.onChangeIssueTypeSpec()"
+                    required>
+                <option ng-repeat="issueStatus in vm.completeIssueStatuses"
+                        ng-style="{ 'color' : issueStatus.color, 'font-weight': 600 }"
+                        value="{{issueStatus.id}}"
+                        translate="{{issueStatus.name}}(id:{{issueStatus.id}})">
+                </option>
+            </select>
+        </div>
+    </div>
+    <div class="row modal-footer buttons-on-right">
+        <div class="">
+            <button type="button" class="btn btn-md btn-secondary bold"
+                    ng-click="fn.resetCompleteIssueStatus()"><span translate="common.reset">珥덇린�솕</span>
+            </button>
+            <button type="button" class="btn btn-md btn-primary bold"
+                    js-short-cut
+                    js-short-cut-action="(fn.formCheck(issueStatusForm.$invalid) || $root.spinner) ? null : fn.formSubmitCompleteIssueStatus()"
+                    ng-click="fn.formSubmitCompleteIssueStatus()"><span translate="common.saved">�깮�꽦</span>
+            </button>
+        </div>
+    </div>
+</div>
+
+<label for="issueTypeForm" class="issue-label">
+    <span translate="api.downIssueOverlapSetting">�븯�쐞 �씠�뒋 泥섎━ 湲곗� �빆紐�</span>
+</label>
 <div class="element-box" style="height: 600px">
     <form role="form" name="apiSettingOverlapForm">
         <div class="form-group">
@@ -54,7 +96,7 @@
             <js-autocomplete-multi data-input-name="customField"
                                    selected-model="vm.form.customFields"
                                    search="vm.customFieldName"
-                                   source="fn.getCustomFieldList(vm.customFieldName, vm.form.customFields)"
+                                   source="fn.getIssueTypeCustomFieldList(vm.customFieldName, vm.form.customFields, vm.projectId, vm.issueTypeId)"
                                    input-disabled="false"
                                    translation-texts="{ count : 'common.few', empty : 'common.emptyCustomField' }"
                                    required
@@ -80,3 +122,4 @@
       </div>
     </form>
 </div>
+

--
Gitblit v1.8.0