...

Сценарий(Метод) получения пользователей из Роли|Группы|Орг.структуры

Тема в разделе "Примеры сценариев", создана пользователем lopatin, 5 апр 2023.

  1. lopatin

    lopatin Новичок

    Бывает, что в ходе проекта мы активно используем стандартные группы и орг. структуру для создания ролевой структуры. Очень удобно бывает использовать переменные типа "Роль", но стандартный функционал не позволяет нам, например получить пользователей из вложенной группы или вложенной орг. структуры из той же группы. Данная функция работает с применением рекурсии, но она ограничивается (бесконечная рекурсия невозможна). Думаю, данную функцию можно улучшить, предлагайте свои улучшения -)
    Код:
    
    // Метод получения пользователей из роли|группы|орг.структуры. Особенности:
    // Метод возвращает пользователей из группы с учетом вложенности. Бесконечная рекурсия возможна, но она ограничивается значением limit_nesting (не советую ставить слишком высокое значение)
    // Метод также успешно возвращает пользователей из вложенной в группу орг. структуры
    // В случае если орг.структура это отдел, метод возвращает всех сотрудников из данного отдела. В случае если это группа или должность, то возвращает только пользователей по данным позициям
    // В случае если в роли находится пользователь метод также успешно его вернёт
    async function getUsersFromRole(outside_role Role UserGroupItemRef OrganisationStructureItemRef) : Promise<UserItem[]> {
        const 
    limit_nesting 10 // Максимальный уровень вложенности рекурсивных вызовов

        //#region Разбиваем переменную типа "Role" на "UserGroupItemRef | OrganisationStructureItemRef" для более удобной работы
        
    let user_component UserGroupItemRef OrganisationStructureItemRef
        
    if ((outside_role as any).type === "group" || (outside_role as any).type === "orgstruct" || (outside_role as any).type === "user") { // Это роль - вытягиваем UserGroupItemRef | OrganisationStructureItemRef
            
    let role Role = (outside_role as any)
            if (
    role.type === "group") {
                
    user_component = (await System.userGroups.search().where((f,g) => g.and(f.__deletedAt.eq(null),f.__id.eq(role.code))).first())!
            } else if (
    role.type === "orgstruct") {
                
    user_component = (await System.organisationStructure.search().where((f,g) => g.and(f.__deletedAt.eq(null),f.__id.eq(role.code))).first())!
            } else if (
    role.type === "user") { // Выход из функции
                
    return await System.users.search().where((f,g) => g.and(f.__status.eq(UserStatus.Active),f.__id.eq(role.code))).all()
            }
        } else {
            
    user_component = (outside_role as any)
        }
        
    //#endregion

        //#region Получение пользователей из группы|орг.структуры с применением рекурсии
        
    let users await async function getUsersFromRoleRecursive(user_componentUserGroupItemRef OrganisationStructureItemRef,current_nesting:number) {
            
    // Проверка лимитов рекурсивных вызовов
            
    if (current_nesting limit_nesting) return [];
            
    current_nesting++;

            
    let users UserItem[] = [];
            if (
    user_component.kind === 'group') { // Группа
                
    let group = (user_component as UserGroupItem)
                if (
    group.data.subOrgunitIds && group.data.subOrgunitIds.length 0) {
                    
    // Получение вложенных групп и орг. структур из группы
                    
    let [sub_groupssub_orgstructs] = (await Promise.all([group.subGroups(),System.organisationStructure.search().where((f,g) => g.and(f.__deletedAt.eq(null),f.__id.in(group.data.subOrgunitIds!))).size(10000).all()]));
                    
    // Перебор всех элементов группы
                    
    (await Promise.all(group.data.subOrgunitIds.map((sub_element) => {
                        
    // Группа
                        
    let sub_group_index sub_groups.map(sub_group => sub_group.id).indexOf(sub_element);
                        if (
    sub_group_index != -1) {
                            return 
    getUsersFromRoleRecursive(sub_groups[sub_group_index],current_nesting);
                        }
                        
    // Орг. структура
                        
    let sub_orgstruct_index sub_orgstructs.map(sub_orgstruct => sub_orgstruct.id).indexOf(sub_element);
                        if (
    sub_orgstruct_index != -1) {
                            return 
    getUsersFromRoleRecursive(sub_orgstructs[sub_orgstruct_index],current_nesting);
                        }
                        
    // Пользователь
                        
    return System.users.search().where((f,g) => g.and(f.__status.eq(UserStatus.Active),f.__id.eq(sub_element))).all();
                    }))).
    map(sub_users => users users.concat(sub_users));

                }
            } else if (
    user_component.kind === 'orgstruct') { // Орг. структура
                
    let orgstruct = (user_component as OrganisationStructureItem)
                if (
    orgstruct && orgstruct.data.type === "DEPARTMENT") { // Если выбран отдел, то включаем всех сотрудников из отдела
                    
    let children_orgstructs getChildrenOrgs(orgstruct);
                    
    users await System.users.search().where((f,g) => {
                        
    let orgstruct_filters Filter[] = []
                        
    children_orgstructs.forEach(children_orgstruct => {
                            
    orgstruct_filters.push(f.osIds.has(children_orgstruct))
                        })
                        return 
    g.and(f.__status.eq(UserStatus.Active),g.or(...orgstruct_filters))
                    }).
    size(10000).all()
                } else if (
    orgstruct) { // Если выбрана группа или должность, то включаем только их
                    
    users users.concat(await System.users.search().where((f,g) => g.and(f.__status.eq(UserStatus.Active),f.osIds.has(orgstruct!))).size(10000).all());
                }
            }
            return 
    users;
        }(
    user_component!,0)
        
    //#endregion
        
    return users;
    }
    Для работы потребуется еще одна функция для получения дочерних орг. структур организационного элемента
    Код:
    
    // Получение дочерних орг.структур
    function getChildrenOrgs(orgItem OrganisationStructureItem) : OrganisationStructureItem[] {
        
    let childrenIDs OrganisationStructureItem[] = []
        for (
    let childrenOrgItem of orgItem.getChildren()) {
            if (
    childrenOrgItem.getChildren().length 0) {
                
    childrenIDs childrenIDs.concat(getChildrenOrgs(childrenOrgItem))
            }
            
    childrenIDs.push(childrenOrgItem)
        }
        return 
    childrenIDs
    }