From 4f4fd9ee8b3315bc433b1893dbff008efdb03230 Mon Sep 17 00:00:00 2001
From: jhjang <jhjang@maprex.co.kr>
Date: 수, 22 12월 2021 16:36:06 +0900
Subject: [PATCH] - API 설정 화면에서 프로젝트에서 설정된 이슈유형만 보여주도록 수정

---
 src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java                  |   16 
 src/main/java/kr/wisestone/owl/repository/IssueTypeApiEndStatusRepository.java     |   23 +
 src/main/java/kr/wisestone/owl/service/impl/CustomFieldApiOverlapServiceImpl.java  |    5 
 src/main/java/kr/wisestone/owl/service/IssueTypeApiEndStatusService.java           |    9 
 src/main/java/kr/wisestone/owl/domain/IssueTypeApiEndStatus.java                   |   76 +++++
 src/main/resources/mybatis/query-template/issueType-template.xml                   |    3 
 src/main/webapp/views/api/apiSettingOverlap.html                                   |   52 ---
 src/main/java/kr/wisestone/owl/service/IssueTypeService.java                       |    2 
 src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java                         |    9 
 src/main/java/kr/wisestone/owl/web/controller/IssueTypeApiEndStatusController.java |   46 +++
 src/main/java/kr/wisestone/owl/service/impl/IssueTypeApiEndStatusServiceImpl.java  |   92 ++++++
 src/main/java/kr/wisestone/owl/domain/IssueType.java                               |   13 
 src/main/webapp/scripts/app/api/apiSetting.controller.js                           |  191 ++++++++-----
 src/main/webapp/views/api/apiSettingSpec.html                                      |   42 ---
 src/main/webapp/scripts/config.js                                                  |   24 
 src/main/java/kr/wisestone/owl/domain/CustomFieldApiOverlap.java                   |   13 
 src/main/resources/migration/V1_15__Alter_Table.sql                                |   22 +
 src/main/java/kr/wisestone/owl/web/controller/IssueTypeController.java             |   10 
 src/main/java/kr/wisestone/owl/web/form/IssueTypeApiEndStatusForm.java             |   43 +++
 src/main/webapp/views/api/apiSettingHeader.html                                    |   42 +++
 src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java              |   29 -
 src/main/java/kr/wisestone/owl/web/form/CustomFieldApiOverlapForm.java             |    9 
 src/main/webapp/views/api/apiSetting.html                                          |    3 
 src/main/webapp/views/api/apiSettingColumn.html                                    |   47 ---
 24 files changed, 540 insertions(+), 281 deletions(-)

diff --git a/src/main/java/kr/wisestone/owl/domain/CustomFieldApiOverlap.java b/src/main/java/kr/wisestone/owl/domain/CustomFieldApiOverlap.java
index 49bc65d..3d52d10 100644
--- a/src/main/java/kr/wisestone/owl/domain/CustomFieldApiOverlap.java
+++ b/src/main/java/kr/wisestone/owl/domain/CustomFieldApiOverlap.java
@@ -16,6 +16,11 @@
     private User user;
 
     @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "project_id")
+    private Project project;
+
+
+    @ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "issue_type_id")
     private IssueType issueType;
 
@@ -60,4 +65,12 @@
     public void setCustomField(CustomField customField) {
         this.customField = customField;
     }
+
+    public Project getProject() {
+        return project;
+    }
+
+    public void setProject(Project project) {
+        this.project = project;
+    }
 }
diff --git a/src/main/java/kr/wisestone/owl/domain/IssueType.java b/src/main/java/kr/wisestone/owl/domain/IssueType.java
index 1e0ca66..1fffcee 100644
--- a/src/main/java/kr/wisestone/owl/domain/IssueType.java
+++ b/src/main/java/kr/wisestone/owl/domain/IssueType.java
@@ -35,9 +35,8 @@
     @JoinColumn(name = "project_id")
     private Project project;
 
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "complete_issue_status_id")
-    private IssueStatus issueStatus;
+    @OneToMany(mappedBy = "issueType", cascade = {CascadeType.ALL}, orphanRemoval = true)
+    private Set<IssueTypeApiEndStatus> issueTypeApiEndStatuses;
 
     /*@ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "company_id")
@@ -138,11 +137,11 @@
         this.usePartner = usePartner;
     }
 
-    public IssueStatus getIssueStatus() {
-        return issueStatus;
+    public Set<IssueTypeApiEndStatus> getIssueTypeApiEndStatuses() {
+        return issueTypeApiEndStatuses;
     }
 
-    public void setIssueStatus(IssueStatus issueStatus) {
-        this.issueStatus = issueStatus;
+    public void setIssueTypeApiEndStatuses(Set<IssueTypeApiEndStatus> issueTypeApiEndStatuses) {
+        this.issueTypeApiEndStatuses = issueTypeApiEndStatuses;
     }
 }
diff --git a/src/main/java/kr/wisestone/owl/domain/IssueTypeApiEndStatus.java b/src/main/java/kr/wisestone/owl/domain/IssueTypeApiEndStatus.java
new file mode 100644
index 0000000..3fc27ff
--- /dev/null
+++ b/src/main/java/kr/wisestone/owl/domain/IssueTypeApiEndStatus.java
@@ -0,0 +1,76 @@
+package kr.wisestone.owl.domain;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+public class IssueTypeApiEndStatus extends BaseEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "user_id")
+    private User user;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "project_id")
+    private Project project;
+
+
+    @OneToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "issue_type_id")
+    private IssueType issueType;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "issue_status_id")
+    private IssueStatus issueStatus;
+
+    public IssueTypeApiEndStatus(){}
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public User getUser() {
+        return user;
+    }
+
+    public void setUser(User user) {
+        this.user = user;
+    }
+
+    public IssueType getIssueType() {
+        return issueType;
+    }
+
+    public void setIssueType(IssueType issueType) {
+        this.issueType = issueType;
+    }
+
+    public Project getProject() {
+        return project;
+    }
+
+    public void setProject(Project project) {
+        this.project = project;
+    }
+
+    public IssueStatus getIssueStatus() {
+        return issueStatus;
+    }
+
+    public void setIssueStatus(IssueStatus issueStatus) {
+        this.issueStatus = issueStatus;
+    }
+}
diff --git a/src/main/java/kr/wisestone/owl/repository/IssueTypeApiEndStatusRepository.java b/src/main/java/kr/wisestone/owl/repository/IssueTypeApiEndStatusRepository.java
new file mode 100644
index 0000000..92b3a8c
--- /dev/null
+++ b/src/main/java/kr/wisestone/owl/repository/IssueTypeApiEndStatusRepository.java
@@ -0,0 +1,23 @@
+package kr.wisestone.owl.repository;
+
+import kr.wisestone.owl.domain.IssueType;
+import kr.wisestone.owl.domain.IssueTypeApiEndStatus;
+import kr.wisestone.owl.domain.Project;
+import kr.wisestone.owl.domain.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+import javax.inject.Named;
+import javax.inject.Qualifier;
+import javax.persistence.NamedQuery;
+import java.util.List;
+
+public interface IssueTypeApiEndStatusRepository extends JpaRepository<IssueTypeApiEndStatus, Long> {
+
+    IssueTypeApiEndStatus findByUserIdAndProjectIdAndIssueTypeId(
+            @Param("user_id") Long userId, @Param("project_id") Long projectId, @Param("issue_type_id") Long issueTypeId);
+
+    void deleteByUserIdAndProjectIdAndIssueTypeId(
+            @Param("user_id") Long userId, @Param("project_id") Long projectId, @Param("issue_type_id") Long issueTypeId);
+}
diff --git a/src/main/java/kr/wisestone/owl/service/IssueTypeApiEndStatusService.java b/src/main/java/kr/wisestone/owl/service/IssueTypeApiEndStatusService.java
new file mode 100644
index 0000000..efbb733
--- /dev/null
+++ b/src/main/java/kr/wisestone/owl/service/IssueTypeApiEndStatusService.java
@@ -0,0 +1,9 @@
+package kr.wisestone.owl.service;
+
+import kr.wisestone.owl.domain.IssueTypeApiEndStatus;
+import kr.wisestone.owl.web.form.IssueTypeApiEndStatusForm;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface IssueTypeApiEndStatusService extends AbstractService<IssueTypeApiEndStatus, Long, JpaRepository<IssueTypeApiEndStatus, Long>> {
+    void setApiEndStatus(IssueTypeApiEndStatusForm issueTypeApiEndStatusForm);
+}
diff --git a/src/main/java/kr/wisestone/owl/service/IssueTypeService.java b/src/main/java/kr/wisestone/owl/service/IssueTypeService.java
index 1f7a4c1..df8c3fc 100644
--- a/src/main/java/kr/wisestone/owl/service/IssueTypeService.java
+++ b/src/main/java/kr/wisestone/owl/service/IssueTypeService.java
@@ -33,8 +33,6 @@
 
     IssueType modifyIssueType(IssueTypeForm issueTypeForm);
 
-    IssueType modifyIssueTypeCompleteIssueStatus(IssueTypeForm issueTypeForm);
-
     IssueType getIssueType(Long id);
 
     List<IssueType> findByProjectId(Long projectId);
diff --git a/src/main/java/kr/wisestone/owl/service/impl/CustomFieldApiOverlapServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/CustomFieldApiOverlapServiceImpl.java
index 4a483e6..5db4424 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/CustomFieldApiOverlapServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/CustomFieldApiOverlapServiceImpl.java
@@ -33,6 +33,9 @@
     private IssueTypeService issueTypeService;
 
     @Autowired
+    private ProjectService projectService;
+
+    @Autowired
     private CustomFieldService customFieldService;
 
     @Override
@@ -72,6 +75,7 @@
     @Transactional
     public boolean modify(Map<String, Object> resJsonData, CustomFieldApiOverlapForm form) {
         User user = this.webAppUtil.getLoginUserObject();
+        Project project = this.projectService.getProject(form.getProjectId());
         List<CustomFieldApiOverlap> customFieldApiOverlaps = this.customFieldApiOverlapRepository.findByUserIdAndIssueTypeId(user.getId(), form.getIssueTypeId());
         if (customFieldApiOverlaps != null && customFieldApiOverlaps.size() > 0) {
             this.customFieldApiOverlapRepository.deleteAll(customFieldApiOverlaps);
@@ -84,6 +88,7 @@
             customFieldApiOverlap.setCustomField(customField);
             customFieldApiOverlap.setUser(user);
             customFieldApiOverlap.setIssueType(this.issueTypeService.getIssueType(form.getIssueTypeId()));
+            customFieldApiOverlap.setProject(project);
 
             customFieldApiOverlapList.add(customFieldApiOverlap);
         }
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 af302ce..24c5547 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -1796,16 +1796,22 @@
                 Issue modifyIssue = this.modifyIssueForApi(user, issueForm, files);
                 Issue parentIssue = modifyIssue.getParentIssue();
                 IssueType issueType = modifyIssue.getIssueType();
-                IssueStatus issueStatus = issueType.getIssueStatus();
+
+                Set<IssueTypeApiEndStatus> issueTypeApiEndStatuses = issueType.getIssueTypeApiEndStatuses();
+                IssueTypeApiEndStatus issueStatus = null;
+                if (issueTypeApiEndStatuses != null && issueTypeApiEndStatuses.size() > 0) {
+                    issueStatus = issueTypeApiEndStatuses.iterator().next();
+                } else {
+                    throw new OwlRuntimeException(this.messageAccessor.getMessage(MsgConstants.API_COMPLETE_ISSUE_STATUS_NOT_EXIST));
+                }
+
                 if (parentIssue != null) {
-                    if (issueStatus == null) {
-                        throw new OwlRuntimeException(this.messageAccessor.getMessage(MsgConstants.API_COMPLETE_ISSUE_STATUS_NOT_EXIST));
-                    }
+
                     IssueCondition issueCondition = new IssueCondition(issueVo.getId(), parentIssue.getId());
                     List<Map<String, Object>> results = this.issueMapper.findNotCompleteByParentIssueId(issueCondition);
                     // �븯�쐞 �씪媛먯씠 紐⑤몢 醫낅즺 �긽�깭�씪�븣 �긽�쐞 �씪媛먮룄 醫낅즺 泥섎━
                     if (results == null || results.size() == 0) {
-                        parentIssue.setIssueStatus(issueType.getIssueStatus());
+                        parentIssue.setIssueStatus(issueStatus.getIssueStatus());
                         this.issueRepository.saveAndFlush(parentIssue);
                     }
                 }
diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueTypeApiEndStatusServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueTypeApiEndStatusServiceImpl.java
new file mode 100644
index 0000000..87bf282
--- /dev/null
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueTypeApiEndStatusServiceImpl.java
@@ -0,0 +1,92 @@
+package kr.wisestone.owl.service.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jws;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import kr.wisestone.owl.constant.MsgConstants;
+import kr.wisestone.owl.domain.*;
+import kr.wisestone.owl.exception.OwlRuntimeException;
+import kr.wisestone.owl.repository.ApiTokenRepository;
+import kr.wisestone.owl.repository.IssueTypeApiEndStatusRepository;
+import kr.wisestone.owl.service.IssueStatusService;
+import kr.wisestone.owl.service.IssueTypeApiEndStatusService;
+import kr.wisestone.owl.service.IssueTypeService;
+import kr.wisestone.owl.service.ProjectService;
+import kr.wisestone.owl.util.ConvertUtil;
+import kr.wisestone.owl.util.DateUtil;
+import kr.wisestone.owl.util.WebAppUtil;
+import kr.wisestone.owl.vo.ApiTokenVo;
+import kr.wisestone.owl.vo.UserVo;
+import kr.wisestone.owl.web.form.ApiTokenForm;
+import kr.wisestone.owl.web.form.IssueTypeApiEndStatusForm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+import java.util.List;
+
+@Service
+public class IssueTypeApiEndStatusServiceImpl extends AbstractServiceImpl<IssueTypeApiEndStatus, Long, JpaRepository<IssueTypeApiEndStatus, Long>> implements IssueTypeApiEndStatusService {
+    @Autowired
+    private IssueTypeApiEndStatusRepository issueTypeApiEndStatusRepository;
+
+    @Autowired
+    private ProjectService projectService;
+
+    @Autowired
+    private IssueTypeService issueTypeService;
+
+    @Autowired
+    private IssueStatusService issueStatusService;
+
+    @Override
+    protected JpaRepository<IssueTypeApiEndStatus, Long> getRepository() {
+        return this.issueTypeApiEndStatusRepository;
+    }
+
+    // 醫낅즺 �긽�깭 �꽕�젙
+    @Override
+    @Transactional
+    public void setApiEndStatus(IssueTypeApiEndStatusForm issueTypeApiEndStatusForm) {
+        User user = this.webAppUtil.getLoginUserObject();
+        Project project = this.projectService.getProject(issueTypeApiEndStatusForm.getProjectId());
+        IssueType issueType = this.issueTypeService.getIssueType(issueTypeApiEndStatusForm.getIssueTypeId());
+
+        if (issueTypeApiEndStatusForm.getIssueStatusId() == null) {
+            // 湲곗〈 �꽕�젙 �궘�젣
+            this.issueTypeApiEndStatusRepository.deleteByUserIdAndProjectIdAndIssueTypeId(
+                    user.getId(), issueTypeApiEndStatusForm.getProjectId(), issueTypeApiEndStatusForm.getIssueTypeId());
+
+        } else {
+            IssueStatus issueStatus = this.issueStatusService.getIssueStatus(issueTypeApiEndStatusForm.getIssueStatusId());
+
+            // 湲곗〈 �꽕�젙 李얘린
+            IssueTypeApiEndStatus issueTypeApiEndStatus = this.issueTypeApiEndStatusRepository.findByUserIdAndProjectIdAndIssueTypeId(
+                    user.getId(), issueTypeApiEndStatusForm.getProjectId(), issueTypeApiEndStatusForm.getIssueTypeId());
+
+            if (issueTypeApiEndStatus != null) {
+                issueTypeApiEndStatus.setIssueStatus(issueStatus);
+                this.issueTypeApiEndStatusRepository.save(issueTypeApiEndStatus);
+            } else {
+                // �깉濡� �꽕�젙
+
+                IssueTypeApiEndStatus newIssueTypeApiEndStatus = ConvertUtil.copyProperties(issueTypeApiEndStatusForm, IssueTypeApiEndStatus.class);
+                newIssueTypeApiEndStatus.setUser(user);
+                newIssueTypeApiEndStatus.setProject(project);
+                newIssueTypeApiEndStatus.setIssueType(issueType);
+                newIssueTypeApiEndStatus.setIssueStatus(issueStatus);
+
+                this.issueTypeApiEndStatusRepository.save(newIssueTypeApiEndStatus);
+            }
+        }
+    }
+
+}
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 78c915a..ac67ca1 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java
@@ -33,6 +33,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 @Service
 public class IssueTypeServiceImpl extends AbstractServiceImpl<IssueType, Long, JpaRepository<IssueType, Long>> implements IssueTypeService {
@@ -270,9 +271,11 @@
         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));
+            Set<IssueTypeApiEndStatus> issueTypeApiEndStatuses = issueType.getIssueTypeApiEndStatuses();
+            if (issueTypeApiEndStatuses != null && issueTypeApiEndStatuses.size() > 0) {
+                IssueTypeApiEndStatus issueTypeApiEndStatus = issueTypeApiEndStatuses.iterator().next();
+
+                issueTypeVo.setCompleteIssueStatusVo(ConvertUtil.copyProperties(issueTypeApiEndStatus.getIssueStatus(), IssueStatusVo.class));
             }
         }
     }
@@ -323,26 +326,6 @@
         }
 
         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;
     }
 
     //  �씠�뒋 �쑀�삎�쓣 �닔�젙�븳�떎.
diff --git a/src/main/java/kr/wisestone/owl/web/controller/IssueTypeApiEndStatusController.java b/src/main/java/kr/wisestone/owl/web/controller/IssueTypeApiEndStatusController.java
new file mode 100644
index 0000000..b9a0df1
--- /dev/null
+++ b/src/main/java/kr/wisestone/owl/web/controller/IssueTypeApiEndStatusController.java
@@ -0,0 +1,46 @@
+package kr.wisestone.owl.web.controller;
+
+import kr.wisestone.owl.constant.Constants;
+import kr.wisestone.owl.service.GuideService;
+import kr.wisestone.owl.service.IssueTypeApiEndStatusService;
+import kr.wisestone.owl.util.ConvertUtil;
+import kr.wisestone.owl.web.condition.GuideCondition;
+import kr.wisestone.owl.web.form.GuideForm;
+import kr.wisestone.owl.web.form.IssueTypeApiEndStatusForm;
+import kr.wisestone.owl.web.form.IssueTypeForm;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Create By J E O N G - S U N / 2019-05-24
+ */
+@Controller
+public class IssueTypeApiEndStatusController extends BaseController {
+
+    @Autowired
+    private IssueTypeApiEndStatusService issueTypeApiEndStatusService;
+
+
+    //  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<>();
+        IssueTypeApiEndStatusForm issueTypeApiEndStatusForm =
+                ConvertUtil.convertMapToClass(params.get(Constants.REQ_KEY_CONTENT), IssueTypeApiEndStatusForm.class);
+
+        this.issueTypeApiEndStatusService.setApiEndStatus(issueTypeApiEndStatusForm);
+        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 de996ab..c503ba4 100644
--- a/src/main/java/kr/wisestone/owl/web/controller/IssueTypeController.java
+++ b/src/main/java/kr/wisestone/owl/web/controller/IssueTypeController.java
@@ -95,14 +95,4 @@
         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/CustomFieldApiOverlapForm.java b/src/main/java/kr/wisestone/owl/web/form/CustomFieldApiOverlapForm.java
index 377c8a7..29bafec 100644
--- a/src/main/java/kr/wisestone/owl/web/form/CustomFieldApiOverlapForm.java
+++ b/src/main/java/kr/wisestone/owl/web/form/CustomFieldApiOverlapForm.java
@@ -12,6 +12,7 @@
     private Long id;
     private Long userId;
     private Long issueTypeId;
+    private Long projectId;
     private List<Long> customFieldIds;
 
     public CustomFieldApiOverlapForm(){}
@@ -64,4 +65,12 @@
             this.customFieldIds.add(customFieldId);
         }
     }
+
+    public Long getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(Long projectId) {
+        this.projectId = projectId;
+    }
 }
diff --git a/src/main/java/kr/wisestone/owl/web/form/IssueTypeApiEndStatusForm.java b/src/main/java/kr/wisestone/owl/web/form/IssueTypeApiEndStatusForm.java
new file mode 100644
index 0000000..34a8cca
--- /dev/null
+++ b/src/main/java/kr/wisestone/owl/web/form/IssueTypeApiEndStatusForm.java
@@ -0,0 +1,43 @@
+package kr.wisestone.owl.web.form;
+
+public class IssueTypeApiEndStatusForm {
+    private Long userId;
+    private Long projectId;
+    private Long issueTypeId;
+    private Long issueStatusId;
+
+    public IssueTypeApiEndStatusForm() {
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public Long getProjectId() {
+        return projectId;
+    }
+
+    public void setProjectId(Long projectId) {
+        this.projectId = projectId;
+    }
+
+    public Long getIssueTypeId() {
+        return issueTypeId;
+    }
+
+    public void setIssueTypeId(Long issueTypeId) {
+        this.issueTypeId = issueTypeId;
+    }
+
+    public Long getIssueStatusId() {
+        return issueStatusId;
+    }
+
+    public void setIssueStatusId(Long issueStatusId) {
+        this.issueStatusId = issueStatusId;
+    }
+}
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 0aa73e3..039f3d9 100644
--- a/src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java
+++ b/src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java
@@ -18,7 +18,6 @@
     private String color;
     private Long workflowId;
     private Long projectId;
-    private Long completeIssueStatusId;
     private List<Long> removeIds = Lists.newArrayList();
     private Long usePartner;
 
@@ -114,13 +113,5 @@
 
     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_15__Alter_Table.sql b/src/main/resources/migration/V1_15__Alter_Table.sql
new file mode 100644
index 0000000..2313994
--- /dev/null
+++ b/src/main/resources/migration/V1_15__Alter_Table.sql
@@ -0,0 +1,22 @@
+ALTER TABLE `custom_field_api_overlap` ADD COLUMN `project_id` bigint(20) DEFAULT NULL;
+ALTER TABLE `custom_field_api_overlap` ADD INDEX `projectIdIndex`(`project_id`);
+
+ALTER TABLE `issue_type` DROP COLUMN `complete_issue_status_id`;
+
+-- �씠�뒋 �옄�룞 醫낅즺 �꽕�젙 �뀒�씠釉�
+CREATE TABLE IF NOT EXISTS `issue_type_api_end_status` (
+    `id` bigint(20) NOT NULL AUTO_INCREMENT,
+    `user_id` bigint(20) DEFAULT NULL,
+    `project_id` bigint(20) DEFAULT NULL,
+    `issue_type_id` bigint(20) DEFAULT NULL,
+    `issue_status_id` bigint(20) DEFAULT NULL,
+    `register_id` bigint(20) NOT NULL COMMENT 'register_id',
+    `register_date` timestamp NULL DEFAULT NULL COMMENT 'register_date',
+    `modify_id` bigint(20) NOT NULL COMMENT 'modify_id',
+    `modify_date` timestamp NULL DEFAULT NULL COMMENT 'modify_date',
+    PRIMARY KEY (`id`),
+    KEY `userIdIndex` (`user_id`),
+    KEY `projectIdIndex` (`project_id`),
+    KEY `issueTypeIdIndex` (`issue_type_id`),
+    KEY `issueStatusIdIndex` (`issue_status_id`)
+    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
diff --git a/src/main/resources/mybatis/query-template/issueType-template.xml b/src/main/resources/mybatis/query-template/issueType-template.xml
index 598fed2..d10b62e 100644
--- a/src/main/resources/mybatis/query-template/issueType-template.xml
+++ b/src/main/resources/mybatis/query-template/issueType-template.xml
@@ -9,8 +9,7 @@
         it.name as name,
         it.description as description,
         it.color as color,
-        it.project_id as projectId,
-        it.complete_issue_status_id as completeIssueStatusId
+        it.project_id as projectId
         FROM
         issue_type it
         INNER JOIN workspace ws on it.workspace_id = ws.id
diff --git a/src/main/webapp/scripts/app/api/apiSetting.controller.js b/src/main/webapp/scripts/app/api/apiSetting.controller.js
index acb070f..2f7e1f6 100644
--- a/src/main/webapp/scripts/app/api/apiSetting.controller.js
+++ b/src/main/webapp/scripts/app/api/apiSetting.controller.js
@@ -9,23 +9,23 @@
     function (app, angular) {
         app.controller('apiSettingController', ['$scope', '$rootScope', '$log', '$resourceProvider','$uibModal', 'SweetAlert',
             '$timeout', '$filter', '$injector', '$controller', 'Api', 'Priority', 'Severity', 'IssueType', 'IssueTypeCustomField',
-            'IssueStatus',
+            'IssueStatus', '$q',
             function ($scope, $rootScope, $log, $resourceProvider, $uibModal, SweetAlert,
                       $timeout, $filter, $injector, $controller, Api, Priority, Severity, IssueType, IssueTypeCustomField,
-                      IssueStatus) {
+                      IssueStatus, $q) {
 
                 $scope.fn = {
                     changeTab : changeTab,
                     getIssueTypeCallback : getIssueTypeCallback,
                     getProjectListCallback : getProjectListCallback,
-                    formSubmit : formSubmit,
+                    formSubmitColumnSetting : formSubmitColumnSetting,
                     formCheck : formCheck,
                     initForm : initForm,
                     getPriorities : getPriorities,
                     getSeverities : getSeverities,
                     onChangeColumnSetting : onChangeColumnSetting,
+                    onChangeEndIssueStatus : onChangeEndIssueStatus,
                     getIssueTypes : getIssueTypes,
-                    onChangeIssueType : onChangeIssueType,
                     reset : reset,
                     resetOverlap : resetOverlap,
                     formSubmitOverlap : formSubmitOverlap,
@@ -42,7 +42,10 @@
                     getProjects : getProjects,
                     formSubmitCompleteIssueStatus : formSubmitCompleteIssueStatus,
                     loadPage : loadPage,
-                    resetCompleteIssueStatus : resetCompleteIssueStatus
+                    resetCompleteIssueStatus : resetCompleteIssueStatus,
+                    findIssueList : findIssueList,
+                    onChangeProject : onChangeProject,
+                    setApiIssueTypeStatus : setApiIssueTypeStatus
                 };
 
                 $scope.vm = {
@@ -103,7 +106,7 @@
 
                 function reset() {
                     $scope.fn.initForm();
-                    $scope.fn.formSubmit();
+                    $scope.fn.formSubmitColumnSetting();
                 }
 
                 // �옄�룞醫낅즺 �꽕�젙 珥덇린�솕
@@ -158,9 +161,7 @@
                                 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();
@@ -188,46 +189,23 @@
                     return issueTypeVo;
                 }
 
-                function onChangeIssueTypeOverlap() {
-                    $scope.fn.getIssueTypeCustomFields();
-                    $scope.fn.getOverlapList();
+                // �옄�룞 �룞猷� �씠�뒋 �긽�깭 蹂�寃쎌떆
+                function onChangeEndIssueStatus() {
+
                 }
 
-                function onChangeIssueType() {
-                    if ($scope.vm.issueTypeId != null) {
-                        let conditions = {
-                            issueTypeId: $scope.vm.issueTypeId
-                        }
-
-                        Api.findApiDefault($resourceProvider.getContent(
-                            conditions, $resourceProvider.getPageContent(0, 1000))).then(function (result) {
-                            $scope.fn.initForm();
-
-                            if (result.data.message.status === "success") {
-                                if (angular.isDefined(result.data.data)) {
-                                    $scope.vm.form.issueApiDefault = result.data.data;
-                                    $scope.vm.form.issueApiDefault.priorityId = result.data.data.priorityId != null ? result.data.data.priorityId.toString() : "";
-                                    $scope.vm.form.issueApiDefault.severityId = result.data.data.severityId != null ? result.data.data.severityId.toString() : "";
-
-
-                                    // if (angular.isDefined(result.data.data.projectVo)) {
-                                    //     $scope.vm.projects = [];
-                                    //     $scope.vm.projects.push(result.data.data.projectVo);
-                                    // }
-                                }
-                            } else {
-                                SweetAlert.swal($filter("translate")("common.failedToIssueTypeDefault"), result.data.message.message, "error"); // "�봽濡쒖젥�듃 紐⑸줉 議고쉶 �떎�뙣"
-                            }
-                        });
-                    }
-
+                function onChangeIssueTypeOverlap() {
+                    $scope.fn.getIssueStatuses();
+                    $scope.fn.getIssueTypeCustomFields();
+                    $scope.fn.getOverlapList();
                 }
 
                 function formSubmitCompleteIssueStatus() {
                     if ($scope.vm.issueTypeId != null) {
                         let content = {
-                            id: $scope.vm.issueTypeId,
-                            completeIssueStatusId: $scope.vm.completeIssueStatusId
+                            issueTypeId : $scope.vm.issueTypeId,
+                            projectId : $scope.vm.projectId,
+                            issueStatusId: $scope.vm.completeIssueStatusId === "none" ? null : $scope.vm.completeIssueStatusId
                         }
 
                         Api.saveCompleteIssueStatus($resourceProvider.getContent(
@@ -235,7 +213,8 @@
 
                             if (result.data.message.status === "success") {
                                 SweetAlert.swal($filter("translate")("api.successToApiAutoCompleteIssueStatus"), result.data.message.message, "success"); // "�꽕�젙 �꽦怨�"
-                                $scope.fn.getIssueTypes();
+                                //$scope.fn.getIssueTypes();
+                                $scope.fn.findIssueList($scope.vm.projectId);
                             } else {
                                 SweetAlert.swal($filter("translate")("api.failedToApiAutoCompleteIssueStatus"), result.data.message.message, "error"); // "�꽕�젙 �떎�뙣"
                             }
@@ -252,14 +231,14 @@
                     return false;
                 }
 
-                function formSubmit() {
+                function formSubmitColumnSetting() {
                     if ($scope.vm.issueTypeId == null)
                         return;
 
                     let condition = {
                         issueTypeId : $scope.vm.issueTypeId,
                         title : $scope.vm.form.issueApiDefault.title,
-                        // projectId : $scope.vm.projects != null && $scope.vm.projects.length > 0 ? $scope.vm.projects[0].id : null,
+                        projectId : $scope.vm.projectId,
                         priorityId : $scope.vm.form.issueApiDefault.priorityId,
                         severityId : $scope.vm.form.issueApiDefault.severityId,
                         description : $scope.vm.form.issueApiDefault.description,
@@ -289,6 +268,7 @@
 
                     let condition = {
                         issueTypeId : $scope.vm.issueTypeId,
+                        projectId : $scope.vm.projectId,
                         customFieldIds : (function () {
                             var ids = [];
 
@@ -400,37 +380,35 @@
                     if (tab === "API_COL_SETTING") {
                         $scope.fn.onChangeColumnSetting();
                     } else if (tab === "API_OVERLAP_SETTING") {
-                        $scope.fn.getIssueStatuses();
                         $scope.fn.onChangeIssueTypeOverlap();
                     } else if (tab === "API_SPEC_SETTING") {
                         $scope.fn.onChangeIssueTypeSpec();
                     }
                 }
 
-                $scope.$on("getIssueStatusComplete", function (event, args){
-                    if ($scope.vm.tab === "API_OVERLAP_SETTING") {
-                        if ($scope.vm.issueStatuses != null) {
-                            $scope.vm.completeIssueStatuses = [];
+                // �옄�룞 醫낅즺 �씠�뒋 �긽�깭 �쟻�슜
+                function setApiIssueTypeStatus() {
+                    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.issueStatuses.forEach(function (issueStatus) {
+                            if (issueStatus.issueStatusType === "CLOSE") {
+                                $scope.vm.completeIssueStatuses.push(issueStatus);
+                            }
+                        });
+
+                        // �꽕�젙�맂 �긽�깭 吏��젙
+                        $scope.vm.completeIssueStatusId = "none";
+                        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();
                                 }
                             });
-
-                            // �꽕�젙�맂 �긽�깭 吏��젙
-                            $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 = {
@@ -443,11 +421,14 @@
                             $scope.vm.issueStatuses = result.data.data;
 
                             // $scope.vm.issueStatusId = "";
-                            if ($scope.vm.issueTypeId === "") {
-                                if ($scope.vm.issueStatuses != null && $scope.vm.issueStatuses.length > 0) {
-                                    $scope.vm.issueStatusId = $scope.vm.issueStatuses[0].id.toString();
-                                }
+                            if ($scope.vm.issueStatuses != null && $scope.vm.issueStatuses.length > 0) {
+                                $scope.vm.issueStatusId = $scope.vm.issueStatuses[0].id.toString();
                             }
+
+                            if ($scope.vm.tab === "API_OVERLAP_SETTING") {
+                                $scope.fn.setApiIssueTypeStatus();
+                            }
+
                             $scope.$broadcast("getIssueStatusComplete", $scope.vm.issueStatuses);
                         } else {
                             SweetAlert.swal($filter("translate")("issue.failedToCriticalListLookup"), result.data.message.message, "error"); // 以묒슂�룄 紐⑸줉 議고쉶 �떎�뙣
@@ -456,11 +437,70 @@
                 }
 
                 function onChangeColumnSetting() {
-                    $scope.fn.getSeverities();
-                    $scope.fn.getPriorities();
-                    $scope.fn.onChangeIssueType();
+                    var promises = {
+                        severities : $scope.fn.getSeverities(),
+                        priorities : $scope.fn.getPriorities(),
+                    }
+                    $q.all(promises).then(function (results) {
+                        if ($scope.vm.issueTypeId != null && $scope.vm.issueTypeId !== "none") {
+                            let conditions = {
+                                issueTypeId: $scope.vm.issueTypeId
+                            }
+
+                            Api.findApiDefault($resourceProvider.getContent(
+                                conditions, $resourceProvider.getPageContent(0, 1000))).then(function (result) {
+                                $scope.fn.initForm();
+
+                                if (result.data.message.status === "success") {
+                                    if (angular.isDefined(result.data.data)) {
+                                        $scope.vm.form.issueApiDefault = result.data.data;
+                                        $scope.vm.form.issueApiDefault.priorityId = result.data.data.priorityId != null ? result.data.data.priorityId.toString() : "";
+                                        $scope.vm.form.issueApiDefault.severityId = result.data.data.severityId != null ? result.data.data.severityId.toString() : "";
+                                    }
+                                } else {
+                                    SweetAlert.swal($filter("translate")("common.failedToIssueTypeDefault"), result.data.message.message, "error"); // "�봽濡쒖젥�듃 紐⑸줉 議고쉶 �떎�뙣"
+                                }
+                            });
+                        }
+
+                    });
                 }
 
+                // �봽濡쒖젥�듃 蹂�寃쎌떆
+                function onChangeProject() {
+                    $scope.fn.findIssueList($scope.vm.projectId);
+                }
+
+                // �씠�뒋 �쑀�삎 紐⑸줉 媛��졇�삤湲�
+                function findIssueList(projectId) {
+                    if ($rootScope.projects == null || $rootScope.projects.length <= 1)
+                        return;
+
+                    //  �씠�뒋 ���엯 紐⑸줉 寃��깋 議곌굔�쓣 留뚮뱺�떎.
+                    var conditions = {
+                        projectId : projectId > -1 ? projectId : null,
+                        useProject : true,
+                        deep : "01" //  �씠�뒋 �쑀�삎�뿉 �뿰寃곕맂 �썙�겕�뵆濡쒖슦 �젙蹂대�� 李얜뒗�떎.
+                    }
+                    IssueType.find($resourceProvider.getContent(conditions,
+                        $resourceProvider.getPageContent(0, 100))).then(function (result) {
+
+                        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();
+                                $scope.fn.getIssueStatuses();
+                                $scope.fn.getIssueTypeCustomFields();
+                            } else {
+                                $scope.vm.issueTypeId = "none";
+                            }
+                        }
+                        else {
+                            SweetAlert.error($filter("translate")("managementType.failedToIssueTypeList"), result.data.message.message); // "�씠�뒋 �쑀�삎 紐⑸줉 議고쉶 �떎�뙣"
+                        }
+
+                    });
+                }
 
                 function onChangeIssueTypeSpec() {
                     $scope.fn.getIssueStatuses();
@@ -514,7 +554,8 @@
                     if ($rootScope.projects != null && $rootScope.projects.length > 0) {
                         // 怨듯넻 �뜲�씠�꽣 遺덈윭�삤湲�
                         $scope.fn.getProjects();
-                        $scope.fn.getIssueTypes();
+                        $scope.fn.findIssueList($scope.vm.projectId);
+                        // $scope.fn.getIssueTypes();
                     }
                 }, true);
 
@@ -534,6 +575,8 @@
                     }
                 }
 
-
+                if ($scope.vm.tab === "") {
+                    $scope.fn.changeTab("API_COL_SETTING");
+                }
             }]);
     });
diff --git a/src/main/webapp/scripts/config.js b/src/main/webapp/scripts/config.js
index 46524b3..60ab2f5 100644
--- a/src/main/webapp/scripts/config.js
+++ b/src/main/webapp/scripts/config.js
@@ -285,17 +285,17 @@
                     return false;
                 };
 
-                $rootScope.getMyInfo = function () {
-
-                    User.findMyLevelAndDepartment($resourceProvider.getContent({},
-                        $resourceProvider.getPageContent(0, 0))).then(function (result) {
-
-                        if (result.data.message.status === "success") {
-                            $rootScope.myLevel = result.data.data.levelName
-                            $rootScope.myDepartments = result.data.data.departmentName
-                        }
-                    });
-                }
+                // $rootScope.getMyInfo = function () {
+                //
+                //     User.findMyLevelAndDepartment($resourceProvider.getContent({},
+                //         $resourceProvider.getPageContent(0, 0))).then(function (result) {
+                //
+                //         if (result.data.message.status === "success") {
+                //             $rootScope.myLevel = result.data.data.levelName
+                //             $rootScope.myDepartments = result.data.data.departmentName
+                //         }
+                //     });
+                // }
 
                 /*$rootScope.checkMngPermissionViewIssueAndProject = function (userPermission) {
                     if (!$rootScope.isDefined($rootScope.user)) {
@@ -549,7 +549,7 @@
                     //  �씠�뒋 紐⑸줉->�긽�꽭�솕硫댁뿉�꽌 留덉�留됱쑝濡� �젒洹쇳븳 �씠�뒋 �븘�씠�뵒 - �씪�슦�듃 �깉�븣留덈떎 珥덇린�솕
                     $rootScope.currentDetailIssueId = null;
                     // �궗�슜�옄 �젙蹂대�� 媛��졇�삩�떎.
-                    $rootScope.getMyInfo();
+                    // $rootScope.getMyInfo();
 
                     $log.debug("toState.name : ", toState.name);
                     $log.debug("$rootScope.previousStateName �솗�씤 : ", $rootScope.previousStateName);
diff --git a/src/main/webapp/views/api/apiSetting.html b/src/main/webapp/views/api/apiSetting.html
index 37a70fc..8c04e76 100644
--- a/src/main/webapp/views/api/apiSetting.html
+++ b/src/main/webapp/views/api/apiSetting.html
@@ -25,12 +25,15 @@
 
             <div class="tab-content mt-30">
                 <div ng-show="vm.tab == 'API_SPEC_SETTING'">
+                    <div ng-include include-replace src="'views/api/apiSettingHeader.html'"></div>
                     <div ng-include include-replace src="'views/api/apiSettingSpec.html'"></div>
                 </div>
                 <div ng-show="vm.tab == 'API_COL_SETTING'">
+                    <div ng-include include-replace src="'views/api/apiSettingHeader.html'"></div>
                     <div ng-include include-replace src="'views/api/apiSettingColumn.html'"></div>
                 </div>
                 <div ng-show="vm.tab == 'API_OVERLAP_SETTING'">
+                    <div ng-include include-replace src="'views/api/apiSettingHeader.html'"></div>
                     <div ng-include include-replace src="'views/api/apiSettingOverlap.html'"></div>
                 </div>
               </div>
diff --git a/src/main/webapp/views/api/apiSettingColumn.html b/src/main/webapp/views/api/apiSettingColumn.html
index b471b43..7b6c148 100644
--- a/src/main/webapp/views/api/apiSettingColumn.html
+++ b/src/main/webapp/views/api/apiSettingColumn.html
@@ -1,46 +1,3 @@
-<div class="row">
-    <div class="col-md-4" ng-if="false">
-        <div class="form-group mb10">
-            <label for="projectForm" class="issue-label">
-                <span translate="common.project">�봽濡쒖젥�듃</span>
-            </label>
-            <select id="projectForm"
-                    name="project"
-                    class="form-control input-sm issue-select-label"
-                    ng-model="vm.projectId"
-                    ng-change="fn.onChangeIssueTypeSpec()"
-                    required>
-                <option ng-repeat="project in vm.projects"
-                        value="{{project.id}}"
-                        translate="{{project.name}}(id:{{project.id}})">
-                </option>
-            </select>
-        </div>
-    </div>
-    <div class="col-md-4">
-        <div class="form-group mb10">
-            <label for="issueTypeForm" class="issue-label">
-                <span translate="issue.issueType">�씠�뒋 �쑀�삎</span>
-            </label>
-            <select id="issueTypeForm"
-                    name="issueType"
-                    class="form-control input-sm issue-select-label"
-                    ng-model="vm.issueTypeId"
-                    ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }"
-                    ng-change="fn.onChangeIssueType()"
-                    required>
-                <option ng-repeat="issueType in vm.issueTypes"
-                        ng-style="{ 'color' : issueType.color, 'font-weight': 600 }"
-                        value="{{issueType.id}}"
-                        translate="{{issueType.name}}(id:{{issueType.id}})">
-                </option>
-            </select>
-        </div>
-
-    </div>
-
-</div>
-
 <div class="element-box">
     <form role="form" name="apiSettingColumnForm">
         <div class="form-group mb10">
@@ -140,8 +97,8 @@
         </button>
         <button type="button" class="btn btn-md btn-primary bold"
                 js-short-cut
-                js-short-cut-action="(fn.formCheck(apiSettingColumnForm.$invalid) || $root.spinner) ? null : fn.formSubmit()"
-                ng-click="fn.formSubmit()"><span translate="common.saved">�깮�꽦</span>
+                js-short-cut-action="(fn.formCheck(apiSettingColumnForm.$invalid) || $root.spinner) ? null : fn.formSubmitColumnSetting()"
+                ng-click="fn.formSubmitColumnSetting()"><span translate="common.saved">�깮�꽦</span>
         </button>
     </div>
 </div>
diff --git a/src/main/webapp/views/api/apiSettingHeader.html b/src/main/webapp/views/api/apiSettingHeader.html
new file mode 100644
index 0000000..587455e
--- /dev/null
+++ b/src/main/webapp/views/api/apiSettingHeader.html
@@ -0,0 +1,42 @@
+<div class="row">
+    <div class="col-md-4">
+        <div class="form-group mb10">
+            <label for="projectForm" class="issue-label">
+                <span translate="common.project">�봽濡쒖젥�듃</span>
+            </label>
+            <select id="projectForm"
+                    name="project"
+                    class="form-control input-sm issue-select-label"
+                    ng-model="vm.projectId"
+                    ng-change="fn.onChangeProject()"
+                    required>
+                <option ng-repeat="project in vm.projects"
+                        value="{{project.id}}"
+                        translate="{{project.name}}(id:{{project.id}})">
+                </option>
+            </select>
+        </div>
+    </div>
+    <div class="col-md-4">
+        <div class="form-group mb10">
+            <label for="issueTypeForm" class="issue-label">
+                <span translate="issue.issueType">�씠�뒋 �쑀�삎</span>
+            </label>
+            <select id="issueTypeForm"
+                    name="issueType"
+                    class="form-control input-sm issue-select-label"
+                    ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }"
+                    ng-model="vm.issueTypeId"
+                    ng-change="fn.loadPage()"
+                    required>
+                <option ng-if="vm.issueTypes == null || vm.issueTypes.length == 0" value="none" translate="common.none"></option>
+                <option ng-repeat="issueType in vm.issueTypes"
+                        ng-style="{ 'color' : issueType.color, 'font-weight': 600 }"
+                        value="{{issueType.id}}"
+                        translate="{{issueType.name}}(id:{{issueType.id}})">
+                </option>
+            </select>
+        </div>
+    </div>
+
+</div>
\ No newline at end of file
diff --git a/src/main/webapp/views/api/apiSettingOverlap.html b/src/main/webapp/views/api/apiSettingOverlap.html
index ecfe175..b87b082 100644
--- a/src/main/webapp/views/api/apiSettingOverlap.html
+++ b/src/main/webapp/views/api/apiSettingOverlap.html
@@ -1,52 +1,3 @@
-
-
-<div class="row">
-    <div class="col-md-4" ng-if="false">
-        <div class="form-group mb10">
-            <label for="projectForm" class="issue-label">
-                <span translate="common.project">�봽濡쒖젥�듃</span>
-            </label>
-            <select id="projectForm"
-                    name="project"
-                    class="form-control input-sm issue-select-label"
-                    ng-model="vm.projectId"
-                    ng-change="fn.onChangeIssueTypeSpec()"
-                    required>
-                <option ng-repeat="project in vm.projects"
-                        value="{{project.id}}"
-                        translate="{{project.name}}(id:{{project.id}})">
-                </option>
-            </select>
-        </div>
-    </div>
-    <div class="col-sm-4">
-
-        <div class="element-wrapper">
-            <div class="form-group mb10">
-                <label for="issueTypeForm" class="issue-label">
-                    <span translate="issue.issueType">�씠�뒋 �쑀�삎</span>
-                </label>
-                <select id="issueTypeForm"
-                        name="issueType"
-                        class="form-control input-sm issue-select-label"
-                        ng-model="vm.issueTypeId"
-                        ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }"
-                        ng-change="fn.onChangeIssueTypeOverlap()"
-                        required>
-                    <option ng-repeat="issueType in vm.issueTypes"
-                            ng-style="{ 'color' : issueType.color, 'font-weight': 600 }"
-                            value="{{issueType.id}}"
-                            translate="{{issueType.name}}">
-                    </option>
-                </select>
-            </div>
-        </div>
-
-    </div>
-
-
-</div>
-
 <label for="issueTypeForm" class="issue-label">
     <span translate="api.upIssueCompleteIssueStatus">�긽�쐞 �씠�뒋 �옄�룞醫낅즺 �씠�뒋 �긽�깭 �꽕�젙</span>
 </label>
@@ -62,8 +13,9 @@
                     class="form-control input-sm issue-select-label"
                     ng-style="{ 'color' : fn.getOptionColor(vm.completeIssueStatuses, vm.completeIssueStatusId) }"
                     ng-model="vm.completeIssueStatusId"
-                    ng-change="fn.onChangeIssueTypeOverlap()"
+                    ng-change="fn.onChangeEndIssueStatus()"
                     required>
+                <option value="none" translate="common.select"></option>
                 <option ng-repeat="issueStatus in vm.completeIssueStatuses"
                         ng-style="{ 'color' : issueStatus.color, 'font-weight': 600 }"
                         value="{{issueStatus.id}}"
diff --git a/src/main/webapp/views/api/apiSettingSpec.html b/src/main/webapp/views/api/apiSettingSpec.html
index 8ff0bb2..5b0ed56 100644
--- a/src/main/webapp/views/api/apiSettingSpec.html
+++ b/src/main/webapp/views/api/apiSettingSpec.html
@@ -1,45 +1,3 @@
-<div class="row">
-    <div class="col-md-4">
-        <div class="form-group mb10">
-            <label for="projectForm" class="issue-label">
-                <span translate="common.project">�봽濡쒖젥�듃</span>
-            </label>
-            <select id="projectForm"
-                    name="project"
-                    class="form-control input-sm issue-select-label"
-                    ng-model="vm.projectId"
-                    ng-change="fn.onChangeIssueTypeSpec()"
-                    required>
-                <option ng-repeat="project in vm.projects"
-                        value="{{project.id}}"
-                        translate="{{project.name}}(id:{{project.id}})">
-                </option>
-            </select>
-        </div>
-    </div>
-    <div class="col-md-4">
-        <div class="form-group mb10">
-            <label for="issueTypeForm" class="issue-label">
-                <span translate="issue.issueType">�씠�뒋 �쑀�삎</span>
-            </label>
-            <select id="issueTypeForm"
-                    name="issueType"
-                    class="form-control input-sm issue-select-label"
-                    ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }"
-                    ng-model="vm.issueTypeId"
-                    ng-change="fn.onChangeIssueTypeSpec()"
-                    required>
-                <option ng-repeat="issueType in vm.issueTypes"
-                        ng-style="{ 'color' : issueType.color, 'font-weight': 600 }"
-                        value="{{issueType.id}}"
-                        translate="{{issueType.name}}(id:{{issueType.id}})">
-                </option>
-            </select>
-        </div>
-    </div>
-
-</div>
-
 <div class="element-box">
     <form role="form" name="apiSettingColumnForm">
         <div class="form-group mb10">

--
Gitblit v1.8.0