1. 권한별로 부여된 사용자의 집계를 보여주자.

  • es-role-list.html 수정
        <sc-grid id="gridPanel" data-provider="{{resultList}}" class="flex" editable="true" aggregate="true"
                 selection-able-function="onSelectionOption"
                 on-item-click="onItemClick">
            <cc-grid-toolbar>
                <sc-button text="추가" on-click="onAddRow" auth-s></sc-button>
                <sc-button text="삭제" on-click="onDeleteList" auth-s></sc-button>
                <sc-button text="저장" on-click="onSaveList" auth-s></sc-button>
            </cc-grid-toolbar>
            <sc-grid-columns>
                <sc-data-column data-field="role_cd" header-text="롤코드" width="100" text-align="center" style-name="link" required="true" max-length="18"
                                item-editable-function="onInsertEditable" aggregate-title="합계"></sc-data-column>
                <sc-data-column data-field="role_nm" header-text="롤명" width="150" text-align="left" editable="true" max-length="60"></sc-data-column>
                <sc-checkbox-column data-field="use_yn" header-text="사용여부" width="60" text-align="center" editable="true" display-checkbox="false" checked-value="Y" un-checked-value="N"></sc-checkbox-column>
                
                <sc-group-column    header-text="사용자"
                                    hide-child-headers="false"  width="140">
                    <sc-data-column header-text="내부"
                                    data-field="usr_cnt_b"      width="70"              text-align="right"
                                    data-type="number"          format-type="integer"
                                    aggregate-format="integer"  aggregate-kind="sum"></sc-data-column>
                    <sc-data-column header-text="외부"
                                    data-field="usr_cnt_s"      width="70"              text-align="right"
                                    data-type="number"          format-type="integer"
                                    aggregate-format="integer"  aggregate-kind="sum"></sc-data-column>
                </sc-group-column>
                
            </sc-grid-columns>
            <sc-grid-fields>
                <sc-grid-field data-field="grp_cd"></sc-grid-field>
                <sc-grid-field data-field="map_cnt" data-type="number"></sc-grid-field>
            </sc-grid-fields>
        </sc-grid>

 

  • role.xml 수정
    <select id="findListRole" resultType="map">
    /* auth.findListRole 전체 롤 목록 조회 */
        SELECT
             RH.ROLE_CD
            ,RH.ROLE_NM
            ,RH.ROLE_EN_NM
            ,RH.USE_YN
            ,CONCAT(CONCAT((SELECT COUNT(SYS_ID) FROM ESAAURM WHERE SYS_ID = RH.SYS_ID AND ROLE_CD = RH.ROLE_CD) 
            ,(SELECT COUNT(SYS_ID) FROM ESAAURP WHERE SYS_ID = RH.SYS_ID AND ROLE_CD = RH.ROLE_CD))
            ,(SELECT COUNT(SYS_ID) FROM ESAAURD WHERE SYS_ID = RH.SYS_ID AND ROLE_CD = RH.ROLE_CD)) AS MAP_CNT 
            
            ,ISNULL(T.USR_CNT_B, 0) AS USR_CNT_B
            ,ISNULL(T.USR_CNT_S, 0) AS USR_CNT_S
            
        FROM ESAAURH RH
        LEFT OUTER JOIN    (SELECT  P.SYS_ID 
                            ,       P.ROLE_CD
                            ,       SUM(CASE WHEN U.USR_CLS = 'B' THEN 1 ELSE 0 END)    AS USR_CNT_B
                            ,       SUM(CASE WHEN U.USR_CLS = 'S' THEN 1 ELSE 0 END)    AS USR_CNT_S
                            
                            FROM ESAAURP P
                            JOIN ESAUSER U  ON  U.SYS_ID = P.SYS_ID 
                                            AND U.USR_ID = P.USR_ID
                                            AND U.STS   != 'D'
                                            
                            GROUP BY    P.SYS_ID 
                            ,           P.ROLE_CD ) T   ON  T.SYS_ID  = RH.SYS_ID 
                                                        AND T.ROLE_CD = RH.ROLE_CD
        WHERE
            RH.SYS_ID = #{g.tenant}
        AND RH.STS != 'D'
        <if test="p.role_nm != null and p.role_nm != ''">
            <bind name="namePattern" value="'%' + p.role_nm + '%'" />
            AND (UPPER(RH.ROLE_NM) like UPPER(#{namePattern})
                    OR UPPER(RH.ROLE_EN_NM) LIKE UPPER(#{namePattern})
            )
        </if>
        <if test="p.role_cd != null and p.role_cd != ''">
            <bind name="namePattern2" value="'%' + p.role_cd + '%'" />
            AND UPPER(RH.ROLE_CD) LIKE UPPER(#{namePattern2})
        </if>
    </select>

 

2. 메뉴의 기능사용권한이 하나라도 있다면 이는 곧 해당메뉴에 접근 권한이 있는 것이다.
즉 role과 func은 별개의 데이터가 아니라 func이 role을 결정한다.
따라서 메뉴-롤 매핑제어 Tab은 숨기고 메뉴-기능 Tab에서 기능을 부여 in & out하면 거기에 따라 해당 상위 메뉴의 role권한이 부여되도록 처리한다.
그리고 func의 상위메뉴 권한부여/제거시 하위레벨 메뉴 혹은 기능에도 자동으로 선택해제가 되도록 편의기능제공한다.

  • em-role.html 수정
            <sc-tab-navigation id="tabNavi"  class="flex-6">
            <!--<es-rolemenu-list id="rolemenuList" title-text="롤/메뉴"></es-rolemenu-list>-->
                <es-rolemenufunc-list id="rolemenufuncList" title-text="롤/메뉴기능" ></es-rolemenufunc-list>
                <es-roleuser-list id="roleuserList" title-text="롤/사용자" ></es-roleuser-list>
                <es-roledept-list id="roledeptList" title-text="롤/부서" ></es-roledept-list>
            </sc-tab-navigation>
            // 롤 현황 : 롤코드 선택
            onSelectedRole: function(e, data) {
                var me = this;
                //me.$.rolemenuList.load(data);
                me.$.rolemenufuncList.load(data);
                me.$.roleuserList.load(data);
                me.$.roledeptList.load(data);
            },
            // 롤 현황 조회 시 상세 내용 초기화
            onResetRoleDetail: function() {
                var me = this;
                //me.$.rolemenuList.clear();
                me.$.rolemenufuncList.clear();
                me.$.roleuserList.clear();
                me.$.roledeptList.clear();

                me.$.tabNavi.selectItem(me.$.rolemenuList);
            }

 

  • es-rolemenufunc-list 수정
        <sc-grid id="gridPanel"
                 data-provider="{{resultList}}"
                 class="flex"
                 is-tree="true"
                 editable="true"
                 use-selection="false"
                 on-item-edit-end="onItemEditEnd">
                 
            <cc-grid-toolbar title-text="[[searchParam.role_nm]]" i18n-disabled>
                <sc-button text="펼침" on-click="onExpandAll"   auth-r></sc-button>
                <sc-button text="접기" on-click="onCollapseAll" auth-r></sc-button>
                <sc-button text="저장" on-click="onSaveList"    auth-s></sc-button>
            </cc-grid-toolbar>
            <sc-grid-columns>
                <sc-data-column data-field="menu_nm" header-text="메뉴명" width="250" text-align="left"></sc-data-column>
                <sc-data-column data-field="func_cd" header-text="메뉴/기능코드" width="120" text-align="center" item-label-function="onItemLabel"></sc-data-column>
                <sc-checkbox-column data-field="use_yn" header-text="메뉴/기능권한" width="100" text-align="center" display-checkbox="false" checked-value="Y" un-checked-value="N"
                                    item-editable-function="onUseYnEditable"></sc-checkbox-column>
            </sc-grid-columns>
            <sc-grid-fields>
                <sc-grid-field data-field="up_menu_cd"></sc-grid-field>
                <sc-grid-field data-field="menu_cd"></sc-grid-field>
            </sc-grid-fields>
        </sc-grid>
            load: function(param) {
                var me = this;
                me.set("searchParam.role_cd", param.role_cd);
                me.set("searchParam.role_nm", param.role_nm);
                me.set("searchParam.usr_cls", UT.toNumber(param.usr_cnt_b) >= UT.toNumber(param.usr_cnt_s) ? "B" : "S"); 
                
                me.onFindList();
                me.applyFormula();
            },

            onUseYnEditable: function(data, item){
                var me = this,
                return true;
            },

            onItemEditEnd : function(event)
            {
                var me = this;
                var data = event.detail.data;
                var item = event.detail.item;
                var provider = event.detail.provider;
                var oldValue = event.detail.oldValue;
                var newValue = event.detail.newValue;
                
                switch (item.dataField)
                {
                    case "use_yn" :
                        me.syncUseYnChild(item.nodeIndex, newValue);
                        me.syncUseYnParent(provider.getParentIndex(item.nodeIndex));
                        break;
                }
            },

            syncUseYnChild : function(nodeIndex, checked)
            {
                var me = this;
                var _provider = me.$.gridPanel.getDataProvider();

                var _childIndexes = _provider.getChildIndexes(nodeIndex);

                _childIndexes.forEach(function(nodeIndex, index, array)
                {
                    //var _menu = _provider.getItemAt(nodeIndex);
                    //console.log("child : " + _menu.menu_cd);
                    _provider.setItemAt(nodeIndex, {use_yn:checked});
                    me.syncUseYnChild(nodeIndex, checked);
                });
            },

            syncUseYnParent : function(nodeIndex)
            {
                var me = this;
                var _provider = me.$.gridPanel.getDataProvider();

                if (nodeIndex > -1)
                {
                    var _menu = _provider.getItemAt(nodeIndex);
                    //console.log("parent : " + _menu.menu_cd);
                    if (_provider.filterItems({up_menu_cd:_menu.menu_cd, use_yn:"Y"}).length > 0)
                    {
                        _provider.setItemAt(nodeIndex, {use_yn:"Y"});
                    }
                    else
                    {
                        _provider.setItemAt(nodeIndex, {use_yn:"N"});
                    }
                    
                    nodeIndex = _provider.getParentIndex(nodeIndex);
                    me.syncUseYnParent(nodeIndex);
                }
            },
            
            // 저장
            onSaveList: function() {
                var me = this,
                    provider = me.$.gridPanel.getDataProvider(),
                    message = "STD.N1200"; // 저장 하시겠습니까?

                if(!me.formula('isEditable')){
                    UT.alert(me.translate("STD.E1012",null,me.translate('롤코드')),null,true); //"'{0}'을(를) 선택하십시오"
                    return;
                }

                var inserts = [],
                deletes = [],
                updated = provider.getUpdateItems();

                if (updated.length == 0)
                {
                    // 변경된 내용이 없습니다.
                    UT.alert("STD.N1700");
                    return;
                }
                
                UT.confirm(message, function()
                {
                    for (var i = 0, len = updated.length; i < len; i++)
                    {
                        //console.log(updated[i].menu_cd + " : " + updated[i].func_cd + " : " + updated[i].children);

                        // leaf level의 Func만 갱신대상이다.
                        if (UT.isNotEmpty(updated[i].func_cd))
                        {
                            var row = {
                                    role_cd: me.get("searchParam.role_cd"),
                                    menu_cd: updated[i].up_menu_cd,
                                    func_cd: updated[i].func_cd
                                };
                            
                            if (updated[i].use_yn === "Y")
                            {
                                inserts.push(row);
                            }
                            else
                            {
                                deletes.push(row);
                            }
                        }
                    }
                    me.$.saveList.body = {
                        insertRoleFuncs: inserts,
                        deleteRoleFuncs: deletes
                    };
                    UT.request(me.$.saveList);
                });
            },

            onItemLabel : function(data, item)
            {
                var me = this;
                var _label = data[item.dataField];

                switch (item.dataField)
                {
                    case "func_cd" :
                        _label = UT.isNotEmpty(data.func_cd) ? data.func_cd : data.menu_cd;
                        break;
                }

                return _label;
            },

 

  • RoleFuncService.java 수정
    /**
     * 롤기능 목록을 등록/삭제한다.
     *
     * @author : JongKyu Kim
     * @param param {"insertRoleFuncs", "deleteRoleFuncs"}
     * @return the map<string, object>
     * @Date : 2016. 2. 2
     * @Method Name : saveListRoleFunc
     */
    public Map<String, Object> saveListRoleFunc(Map<String, Object> param) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        List<Map<String, Object>> inserts = (List<Map<String, Object>>)param.get("insertRoleFuncs");
        List<Map<String, Object>> deletes = (List<Map<String, Object>>)param.get("deleteRoleFuncs");
        List<Map<String, Object>> menuList    = Lists.newArrayList();
                
        if (inserts != null && !inserts.isEmpty()) {
            boolean exist = false;
            for (Map<String, Object> row : inserts) {
                if (this.getCountRoleFunc(row) > 0) { // 롤기능 중복 체크
                    exist = true;
                    break;
                }
            }
            if (exist) {
                throw new CommonException(ErrorCode.DUPLICATED);
            }

            for (Map<String, Object> row : inserts) {
                this.insertRoleFunc(row);
                
                // 메뉴권한 처리할 메뉴 중복없이 저장
                Map<String, Object> menu = new HashMap<String, Object>();
                menu.put("menu_cd", row.get("menu_cd"));
                menu.put("role_cd", row.get("role_cd"));
                
                if (!menuList.contains(menu))
                {
                    menuList.add(menu);
                }
            }
        }
        if (deletes != null && !deletes.isEmpty()) {
            for (Map<String, Object> row : deletes) {
                this.deleteRoleFunc(row);
                
                // 메뉴권한 처리할 메뉴 중복없이 저장
                Map<String, Object> menu = new HashMap<String, Object>();
                menu.put("menu_cd", row.get("menu_cd"));
                menu.put("role_cd", row.get("role_cd"));
                
                if (!menuList.contains(menu))
                {
                    menuList.add(menu);
                }
            }
        }
        
        // 메뉴권한 처리
        if (menuList != null && !menuList.isEmpty()) {
            for (Map<String, Object> menu : menuList) {
                List<Map<String, Object>> _menuList = sqlSession.selectList("role.selectReverseMenu", menu);
                
                if (_menuList != null && !_menuList.isEmpty()) {
                    for (Map<String, Object> _menu : _menuList) {
                        sqlSession.update("role.saveMenuRole", _menu);
                    }
                }
            }
        }
        
        return resultMap;
    }

 

  • role.xml 수정
    <select id="findListRoleMenuWithMenuFunc" resultType="map">
    /* findListRoleMenuWithMenuFunc */
         SELECT MM.UP_MENU_CD
              , MM.SYS_ID
              , MM.MENU_CD
              , MM.USR_CLS
              , MM.MENU_TYP
              , MM.MD_CLS
              , MM.SORT_ORD
              , CASE 
                WHEN ML.MENU_NM IS NULL THEN MM.FUNC_NM
                ELSE ML.MENU_NM
                END MENU_NM
              , ML.LANG_CD
              , ML.MENU_CD AS ML_MENU_CD
              , RM.ROLE_CD
--            , CASE 
--                  WHEN RF.FUNC_CD IS NULL OR RF.FUNC_CD = '' THEN 'N' 
--                  ELSE 'Y' 
--              END AS USE_YN
                
              , CASE WHEN COALESCE(RF.FUNC_CD, RM.ROLE_CD) IS NULL THEN 'N' ELSE 'Y' END AS USE_YN
              , MM.FUNC_CD
           FROM (
                SELECT A.UP_MENU_CD
                     , A.SYS_ID
                     , A.MENU_CD
                     , A.USR_CLS
                     , A.MENU_TYP
                     , A.MD_CLS
                     , A.SORT_ORD
                     , '' AS FUNC_NM
                     , '' AS FUNC_CD
                     , A.USE_YN
                     , A.STS
                     , #{p.role_cd} AS ROLE_CD
                  FROM ESAAUMM A
                 WHERE A.SYS_ID = #{g.tenant}
                   AND A.USR_CLS = #{p.usr_cls}
                   AND A.STS != 'D'
                   AND A.USE_YN = 'Y'
                 UNION ALL
                SELECT B.MENU_CD AS UP_MENU_CD
                     , B.SYS_ID
                     , CONCAT(B.MENU_CD, B.FUNC_CD) AS MENU_CD
                     , #{p.usr_cls} AS USR_CLS
                     , '' AS MENU_TYP
                     , '' AS MD_CLS
                     , 0 AS SORT_ORD
                     , B.FUNC_NM
                     , B.FUNC_CD AS FUNC_CD
                     , 'Y' AS USE_YN
                     , 'C' AS STS
                     , #{p.role_cd} AS ROLE_CD
                  FROM ESAAUMF B
           ) MM
           LEFT OUTER JOIN ESAAUML ML
             ON MM.SYS_ID = ML.SYS_ID
            AND MM.MENU_CD = ML.MENU_CD
            AND ML.LANG_CD = #{p.lang_cd}
           LEFT OUTER JOIN ESAAURM RM
             ON MM.SYS_ID = RM.SYS_ID
            AND MM.MENU_CD = RM.MENU_CD
            AND RM.ROLE_CD = #{p.role_cd}
           LEFT OUTER JOIN ESAAURF RF
             ON MM.SYS_ID = RF.SYS_ID
            AND MM.UP_MENU_CD = RF.MENU_CD
            AND MM.ROLE_CD = RF.ROLE_CD
            AND MM.FUNC_CD = RF.FUNC_CD
          WHERE MM.SYS_ID = #{g.tenant}
            AND MM.USR_CLS = #{p.usr_cls}
            AND MM.STS != 'D'
            AND MM.USE_YN = 'Y'
          ORDER BY MM.SORT_ORD
    </select>

    <select id="selectReverseMenu" resultType="map">
        <![CDATA[
        /* role.selectReverseMenu: 메뉴구조 역전개 */
        
        WITH MENU_TREE
        AS
        (
            SELECT  M.SYS_ID
            ,       M.MENU_CD
            ,       M.UP_MENU_CD
            ,       1                                                                                                       AS MENU_LEVEL
            ,       M.SORT_ORD
            ,       M.USE_YN
            ,       M.USR_CLS
            ,       CAST(RIGHT('0000' + CAST(ISNULL(M.SORT_ORD, 99) AS VARCHAR), 4) AS VARCHAR(100))                        AS MENU_SORT_ORDER

            FROM ESAAUMM M
        
            WHERE M.SYS_ID = #{g.tenant}
            AND M.MENU_CD = #{p.menu_cd}
            AND M.USE_YN = 'Y'
            AND M.STS <> 'D' 
            
            UNION ALL
        
            SELECT  M.SYS_ID
            ,       M.MENU_CD
            ,       M.UP_MENU_CD
            ,       T.MENU_LEVEL + 1                                                                                        AS MENU_LEVEL
            ,       M.SORT_ORD
            ,       M.USE_YN
            ,       M.USR_CLS
            ,       CAST(T.MENU_SORT_ORDER + RIGHT('0000' + CAST(ISNULL(M.SORT_ORD, 99) AS VARCHAR), 4) AS VARCHAR(100))    AS MENU_SORT_ORDER
        
            FROM MENU_TREE T
            JOIN ESAAUMM M  ON  M.SYS_ID        = T.SYS_ID
                            AND M.MENU_CD       = T.UP_MENU_CD
                            AND M.USE_YN        = T.USE_YN
                            AND M.STS          <> 'D'
        )
        SELECT  M.MENU_CD
        ,       #{p.role_cd}    AS ROLE_CD
        FROM MENU_TREE M
        ORDER BY M.USR_CLS, M.MENU_SORT_ORDER
        ]]>
    </select>
    
    <update id="saveMenuRole">
        <![CDATA[
        /* role.saveMenuRole: 메뉴Role저장 */
        
        BEGIN
        
            DECLARE @EXISTS_YN  VARCHAR(1) = 'N';
        
            WITH MENU_TREE
            AS
            (
                SELECT  M.SYS_ID
                ,       M.MENU_CD
                ,       M.UP_MENU_CD
                ,       1                                                                                                       AS MENU_LEVEL
                ,       M.SORT_ORD
                ,       M.USE_YN
                ,       M.USR_CLS
                ,       CAST(RIGHT('0000' + CAST(ISNULL(M.SORT_ORD, 99) AS VARCHAR), 4) AS VARCHAR(100))                        AS MENU_SORT_ORDER
    
                FROM ESAAUMM M
                WHERE M.SYS_ID = #{g.tenant}
                AND M.MENU_CD = #{p.menu_cd}
                AND M.USE_YN = 'Y'
                AND M.STS <> 'D' 
            
                UNION ALL
            
                SELECT  M.SYS_ID
                ,       M.MENU_CD
                ,       M.UP_MENU_CD
                ,       T.MENU_LEVEL + 1                                                                                        AS MENU_LEVEL
                ,       M.SORT_ORD
                ,       M.USE_YN
                ,       M.USR_CLS
                ,       CAST(T.MENU_SORT_ORDER + RIGHT('0000' + CAST(ISNULL(M.SORT_ORD, 99) AS VARCHAR), 4) AS VARCHAR(100))    AS MENU_SORT_ORDER
            
                FROM MENU_TREE T
                JOIN ESAAUMM M  ON  M.SYS_ID        = T.SYS_ID
                                AND M.UP_MENU_CD    = T.MENU_CD
                                AND M.USE_YN        = T.USE_YN
                                AND M.STS          <> 'D'
            )
            SELECT @EXISTS_YN = ISNULL(MAX('Y'), 'N')
            WHERE EXISTS   (SELECT  MM.MENU_CD
                            ,       MM.MENU_LEVEL
                            ,       MM.UP_MENU_CD
                            ,       MF.ROLE_CD
                            ,       MF.FUNC_CD
                            FROM MENU_TREE MM
                            JOIN ESAAURF MF ON  MF.SYS_ID   = MM.SYS_ID
                                            AND MF.MENU_CD  = MM.MENU_CD
                                            AND MF.ROLE_CD  = #{p.role_cd});
                                        
            
            -- 해당Role에 메뉴기능이 있다면
            IF @EXISTS_YN = 'Y'
                -- 메뉴Role추가
                INSERT INTO ESAAURM (   SYS_ID
                                    ,   MENU_CD
                                    ,   ROLE_CD
                                    ,   REG_ID
                                    ,   REG_DT)
                            SELECT  #{g.tenant}
                            ,       #{p.menu_cd}
                            ,       #{p.role_cd}
                            ,       #{g.username}
                            ,       #{g.now}
                            WHERE NOT EXISTS   (SELECT 'X'
                                                FROM ESAAURM T
                                                WHERE T.SYS_ID  = #{g.tenant}
                                                AND T.MENU_CD   = #{p.menu_cd}
                                                AND T.ROLE_CD   = #{p.role_cd});
            
            ELSE
                -- 메뉴Role삭제
                DELETE
                FROM ESAAURM
                WHERE SYS_ID    = #{g.tenant}
                AND MENU_CD     = #{p.menu_cd}
                AND ROLE_CD     = #{p.role_cd};
        END;
        ]]>
    </update>

 

3. 사용자의 보유Role을 실시간으로 조회할 수 있는 편의기능을 넣자.

  • es-roleuser-list.html 수정
        <sc-request-group init>
            <sc-code-group>
                <sc-code code="C016" value="{{codes.C016}}"></sc-code>  <!-- 사용자구분 -->
            </sc-code-group>
            <sc-ajax url="getAllCompanyList.do" last-response="{{codes.company}}"></sc-ajax> <!-- 회사 목록 -->
        </sc-request-group>


                <tr>
                    <th><sc-label text="내/외부"></sc-label></th>
                    <td>
                        <sc-combobox-field
                                display-field="label" value-field="data" placeholder="전체" readonly="[[!formula('isEditable')]]"
                                items="{{codes.C016}}" value="{{searchParam.usr_cls}}" selected-index="0">
                        </sc-combobox-field>
                    </td>
                    <th><sc-label text="사용자"></sc-label></th>
                    <td>
                        <div class="field-box">
                            <sc-text-field value="{{searchParam.usr_id}}" placeholder="ID" readonly="[[!formula('isEditable')]]" on-enter="onFindList"></sc-text-field>
                            <div class="hspace-2"></div>
                            <sc-text-field value="{{searchParam.usr_nm}}" placeholder="명" readonly="[[!formula('isEditable')]]" on-enter="onFindList"></sc-text-field>
                        </div>
                    </td>
                </tr>


        <sc-grid id="gridPanel" 
                 data-provider="{{resultList}}"
                 class="flex"
                 editable="true"
                 show-tooltip="true"
                 tooltip-duration="30000"
                 use-selection="false"
                 on-item-click="onItemClick">
                 
            <cc-grid-toolbar title-text=" [[translate('권한코드')]][[roleCdText]]" i18n-disabled>
                <sc-button text="저장" on-click="onSaveList" auth-s></sc-button>
            </cc-grid-toolbar>
            
            <sc-grid-columns>
                <sc-combobox-column header-text="내/외부"
                                    data-field="usr_cls"        width="60"              text-align="center" 
                                    display-field="label"       value-field="data"      items="{{codes.C016}}"></sc-combobox-column>
                                        
                <sc-data-column data-field="usr_id" header-text="아이디" width="100" text-align="center"></sc-data-column>
                <sc-data-column data-field="usr_nm" header-text="이름" width="150" text-align="left"></sc-data-column>
                <sc-data-column data-field="comp_nm" header-text="회사" width="120" text-align="center"></sc-data-column>
                <sc-data-column data-field="dept_nm" header-text="부서" width="120" text-align="left"></sc-data-column>
                <sc-checkbox-column data-field="use_yn" header-text="보유" width="40" text-align="center" editable="true" display-checkbox="false" checked-value="Y" un-checked-value="N"></sc-checkbox-column>

                <sc-group-column    header-text="보유롤"
                                    hide-child-headers="true"       width="240">
                    <sc-data-column     header-text="롤"
                                        data-field="role_nms"       width="200"             text-align="left"
                                        content-tooltip-callback="onContentTooltip"></sc-data-column>
                    <sc-image-column    header-text="조회"
                                        data-field="btn_refresh"    width="40"              text-align="center"
                                        singular-source="/ui/assets/img/trigger-refresh.png"></sc-image-column>
                </sc-group-column>
                
                <sc-date-column data-field="last_login_dt" header-text="최종접속일시" width="130" text-align="center" display-format="yyyy-MM-dd HH:mm:ss"></sc-date-column>
            </sc-grid-columns>
        </sc-grid>
                codes: {
                    type: Object,
                    value: {
                        C016    : [],
                        company : []
                    },
                    reset: false
                },

            load: function(param) {
                var me = this;
                me.set("searchParam.role_cd", param.role_cd);
                me.set("searchParam.usr_cls", UT.toNumber(param.usr_cnt_b) >= UT.toNumber(param.usr_cnt_s) ? "B" : "S"); 
                me.set("roleCdText", " : " + me.searchParam.role_cd);
                me.onFindList();
                me.applyFormula();
            },

            // 저장 완료
            completeSaveList: function() {
                var me = this,
                    message = "STD.N2400"; // 저장하였습니다.
                UT.alert(message, function(){
                    me.onFindList();

                    me.domHost.$.roleList.onFindList();
                });
            },

            onItemClick : function(event)
            {
                var me = this;
                var data = event.detail.data;
                var item = event.detail.item;
                var provider = event.detail.provider;

                provider.setUpdateIgnoredFields(["role_nms"]);
                
                switch (item.dataField)
                {
                    case "btn_refresh": 
                        var ajax = new SCAjax();
                        ajax.url = "/bp/admin/auth/findUserRole.do";
                        ajax.body = {usr_id:data.usr_id};
                        SCLoadMask.show();
                        ajax.addEventListener("response", function(event)
                        {
                            ajax.removeEventListener(event.type, arguments.callee);
                            
                            var _result = event.target.lastResponse;
                            var _roleNms = UT.isEmpty(_result) ? "N/A" : _result.role_nms;
                            
                            provider.setItemAt(item.rowIndex, {role_nms:_roleNms});
                            SCLoadMask.hide();
                        });
                        ajax.request();
                        break;
                }
            },

            onContentTooltip : function(rowIndex, value, dataFieldName, rowData, displayValue)
            {
                var me = this;
                
                switch (dataFieldName)
                {
                    case "role_nms" :
                        if (UT.isNotEmpty(rowData.role_nms) && rowData.role_nms != "N/A")
                        {
                            return rowData.role_nms.replace(/, /g, "<br/>");
                        }
                        break;
            },

 

  • RoleController.java 수정
    /**
     * 사용자의 보유롤을 조회한다.
     *
     * @author : PJW
     * @param param the param
     * @return The user's role
     * @Date : 2020. 09. 25
     * @Method Name : findUserRole
     */
    @AuthCheck (authCode = Const.READ)
    @RequestMapping (value = "findUserRole.do")
    public @ResponseBody Map<String, Object> findUserRole(@RequestBody Map param) {
        return roleService.findUserRole(param);
    }

 

  • RoleService.java 수정
    /**
     * 사용자의 보유롤을 조회한다.
     *
     * @author : PJW
     * @param param the param
     * @return The user's role
     * @Date : 2020. 09. 25
     * @Method Name : findUserRole
     */
    public Map findUserRole(Map param) {
        return sqlSession.selectOne("role.findUserRole", param);
    }

 

  • role.xml 수정
   <select id="findListRoleUser" resultType="map">
    /* 롤 별 사용자 권한 확인 findListRoleUser*/
        SELECT 
              U.USR_ID
            , U.USR_NM
            , U.COMP_CD
            , U.DEPT_CD
            , U.USR_CLS
            , U.LAST_LOGIN_DT
            , CASE WHEN RP.ROLE_CD IS NULL OR RP.ROLE_CD = '' THEN 'N' ELSE 'Y' END AS USE_YN
            , DP.DEPT_NM
            , MG.ORG_NM AS COMP_NM
            FROM ESAUSER U
            LEFT OUTER JOIN ESAAURP RP
            ON (
                U.SYS_ID = RP.SYS_ID
                AND U.USR_ID = RP.USR_ID
                AND RP.ROLE_CD = #{p.role_cd}
            )
            LEFT OUTER JOIN ESAOGDP DP
            ON (
                U.SYS_ID = DP.SYS_ID
                AND DP.ORG_TYP_CD = 'COMPANY'
                AND U.COMP_CD = DP.ORG_CD
                AND U.DEPT_CD = DP.DEPT_CD
            )
            LEFT OUTER JOIN ESAOGMG MG
            ON (
                U.SYS_ID = MG.SYS_ID
                AND MG.ORG_TYP_CD = 'COMPANY'
                AND U.COMP_CD = MG.ORG_CD
            )
            WHERE U.SYS_ID = #{g.tenant}
            <if test="p.usr_nm != null and p.usr_nm != ''">
                <bind name="namePattern" value="'%' + p.usr_nm + '%'" />
                AND UPPER(u.usr_nm) like UPPER(#{namePattern})
            </if>
            <if test="p.usr_id != null and p.usr_id != ''">
                <bind name="namePattern3" value="'%' + p.usr_id + '%'" />
                AND UPPER(U.USR_ID) like UPPER(#{namePattern3})
            </if>
            <if test="p.dept_nm != null and p.dept_nm != ''">
                <bind name="namePattern2" value="'%' + p.dept_nm + '%'" />
                AND UPPER(DP.DEPT_NM) like UPPER(#{namePattern2})
            </if>
            <if test="p.comp_cd != null and p.comp_cd != ''">
                AND U.COMP_CD = #{p.comp_cd}
            </if>
            <if test="p.usr_cls != null and p.usr_cls != ''">
                AND U.USR_CLS = #{p.usr_cls}
            </if>
            ORDER BY U.USR_CLS, RP.ROLE_CD DESC, U.USR_ID
    </select>

    <select id="findUserRole" resultType="map">
        <![CDATA[
        /* role.findUserRole*/
        SELECT  P.SYS_ID
        ,       P.USR_ID
        ,       STRING_AGG(CONCAT('[', H.ROLE_CD, '] ', H.ROLE_NM), ', ') WITHIN GROUP (ORDER BY H.ROLE_CD) AS ROLE_NMS
        
        FROM ESAAURP P
        JOIN ESAAURH H  ON  H.SYS_ID    = P.SYS_ID
                        AND H.ROLE_CD   = P.ROLE_CD
                        AND H.STS      != 'D'
        
        WHERE P.SYS_ID  = #{g.tenant}
        AND P.USR_ID    = #{p.usr_id}
        
        GROUP BY    P.SYS_ID
        ,           P.USR_ID;
        ]]>
    </select>