Ir para o conteúdo

Lab 4.3: Integrações com o Orquestrador

Nessa etapa, vamos entender como fazer as integrações do Datapool e outras funcionalidades no código da Automação.

O Orquestrador BotCity Maestro oferece uma solução integrada para o gerenciamento de suas automações.

O código possui integração com Alerta, Credenciais, Insights, além do Datapool, permitindo que você tenha uma visão completa do que está acontecendo em suas Automações.

Credenciais

Uma integração importante definida no código é utilização de Credenciais para armazenar informações sensíveis, como login e senha de acesso à plataforma OrangeHRM.

Código

Abra o código de exemplo e veja a função de login na plataforma, os dados para acesso à plataforma estão armazenados no Orquestrador BotCity e são acessados através da funcionalidade de Credenciais.

def login(bot: WebBot, maestro:BotMaestroSDK):
    """Faz o login na plataforma OrangeHRM.

    Args:
        bot: Instancia do framework Web
        maestro: Instancia de conexão com Orquestrador BotCity
    """

    # Seletores dos elementos necessários para login
    element_user = "div.oxd-form-row:nth-child(2) > div:nth-child(1) > div:nth-child(2) > input:nth-child(1)"
    element_password = "div.oxd-form-row:nth-child(3) > div:nth-child(1) > div:nth-child(2) > input:nth-child(1)"
    element_button = ".oxd-button"

    # Uso de credenciais armazenadas no Orquestrador BotCity
    bot.find_element(
        element_user, 
        By.CSS_SELECTOR
        ).send_keys(maestro.get_credential(label="login_orangehrm", key="username"))
    bot.find_element(
        element_password, 
        By.CSS_SELECTOR
        ).send_keys(maestro.get_credential(label="login_orangehrm", key="password"))
    bot.find_element(element_button, By.CSS_SELECTOR).click()

Orquestrador BotCity

Para criar uma nova credencial, acesse o menu lateral Credenciais no Orquestrador, clique em Nova Credencial e preencha os campos:

  • Label: login_orangehrm
  • Repositório: DEFAULT
  • Secrets:
    • Chave: username
    • Valor: Admin
    • Chave: password
    • Valor: admin123

Credentials

Datapool

No projeto de exemplo, temos uma estrutura que permite que uma única tarefa possa processar vários itens do Datapool, pois temos um laço de repetição no código.

Vamos passar por cada etapa.

Conexão

# Obtendo a referência do Datapool
datapool = maestro.get_datapool(label="orange_candidatos")

# Enquanto houver itens para serem processados
while datapool.has_next():
    # Retorna o proximo item disponível do Datapool
    item = datapool.next(task_id=execution.task_id)
    ...

Entendendo a estrutura:

  • datapool = maestro.get_datapool(label="orange_candidatos"): Faz a conexão com o Datapool criado no Orquestrador e armazena a conexão em uma variável.
  • while datapool.has_next(): Laço de repetição que faz a verificação se existe um item na fila do Datapool com o estado Pendente.
  • item = datapool.next(task_id=execution.task_id): Havendo item, as informações dele são armazenadas em uma variável e o vinculadas a uma tarefa.
  • item: essa variável será utilizada para fazer o processamento do item e também reporte de seu estado como sucesso ou falha no processamento.

Processamento

Quando um item capturado da fila de processamento do Datapool, automaticamente o estado dele passa para PROCESSANDO.

Seguindo a estrutura do código, encontraremos a função cadastro, aqui usamos a variável item para acessar os valores do item, conforme definimos do Schema do Datapool.

Veja os destaques na função:

def cadastro(bot: WebBot, item: DataPoolEntry):
    try:
        # Seletores dos elementos necessários para cadastro
        element_first_name = ".orangehrm-firstname"
        element_middle_name = ".orangehrm-middlename"
        element_last_name = ".orangehrm-lastname"
        element_vacancy = "i.bi-caret-down-fill:nth-child(1)"
        element_options = "div.oxd-select-option > span:nth-child(1)"
        element_email = "div.oxd-form-row:nth-child(3) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > input:nth-child(1)"
        element_contact = "div.oxd-form-row:nth-child(3) > div:nth-child(1) > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > input:nth-child(1)"
        element_keywords = "div.oxd-form-row:nth-child(5) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > input:nth-child(1)"
        element_save = "button.oxd-button:nth-child(3)"
        element_recruitment = "li.oxd-main-menu-item-wrapper:nth-child(5)"
        element_add = "button.oxd-button--secondary:nth-child(1)"
        element_field_required = '//span[@class="oxd-text oxd-text--span oxd-input-field-error-message oxd-input-group__message"]'

        # Preenche as informações do candidato
        primeiro_nome = item['full_name'].split(" ")[0]
        nome_meio = item['full_name'].split(" ")[1]
        ultimo_nome = item['full_name'].split(" ")[2:]

        if ultimo_nome:
            bot.find_element(element_first_name, By.CSS_SELECTOR).send_keys(primeiro_nome)
            bot.find_element(element_middle_name, By.CSS_SELECTOR).send_keys(nome_meio)
            bot.find_element(element_last_name, By.CSS_SELECTOR).send_keys(ultimo_nome)
        else:
            bot.find_element(element_first_name, By.CSS_SELECTOR).send_keys(primeiro_nome)
            bot.find_element(element_last_name, By.CSS_SELECTOR).send_keys(nome_meio)

        bot.find_element(element_vacancy, By.CSS_SELECTOR).click()

        options = bot.find_elements(element_options, By.CSS_SELECTOR)
        for option in options:
            if option.text == item['vacancy']:
                option.click()
                break

        bot.find_element(element_email, By.CSS_SELECTOR).send_keys(item['email'])
        bot.find_element(element_contact, By.CSS_SELECTOR).send_keys(item['contact_number'])
        bot.find_element(element_keywords, By.CSS_SELECTOR).send_keys(item['keywords'])

        # Salvar
        bot.find_element(element_save, By.CSS_SELECTOR).click()
        bot.wait(1000)

        # Validando se algum campo obrigatório não foi preenchido
        candidato_cadastrado = True
        required_fields_error = bot.find_elements(element_field_required, By.XPATH)
        if required_fields_error:
            candidato_cadastrado = False

        # Voltar página
        bot.find_element(element_recruitment, By.CSS_SELECTOR).click()
        bot.find_element(element_add, By.CSS_SELECTOR).click()
        bot.wait(1000)
    except:
        candidato_cadastrado = False

    return candidato_cadastrado

Reporte de Estado

Nessa etapa os valores do candidato são cadastrados e salvos na plataforma OrangeHRM, porém podem ocorrer erros no preenchimento dos campos, seja por falta de informação ou dados inválidos, por exemplo.

Para ambos os casos utilizaremos o reporte de estado de cada item no Datapool.

Veja os destaques nesses trechos:

# Faz o cadastro do item (candidato) na plataforma OrangeHRM
candidato_cadastrado = cadastro(bot, item)

if candidato_cadastrado:
    # Reporta para o Datapool que o item foi processado com sucesso
    item.report_done(
        finish_message="Finalizado com sucesso."
    )

    # Soma ao contador de itens processados
    itens_sucesso += 1

else:
    # Reporta para o Datapool que ocorreu uma falha no processamento do item
    item.report_error(
        error_type=ErrorType.BUSINESS,
        finish_message="Por motivos de negócios"
    )

    # Soma ao contador de itens com falha
    itens_falhos += 1
...
except Exception as e:
    bot.save_screenshot("captura.png")
    if item:
        item.report_error(
                error_type=ErrorType.SYSTEM,
                finish_message="Por motivos de sistema"
            )

Atenção

O reporte de erros podem ocorrer de duas formas:

  • Erro de negócios
  • Erro de sistema

Dependendo do tipo de erro, algumas ações serão disparadas ou não, veja mais detalhes na documentação do Datapool.

BotCity Insights

O BotCity Insights utiliza como base para os cálculos a quantidade de itens que uma tarefa executou. Essa será uma unidade essencial para o cálculo de desempenho e dados financeiros.

Você pode entender item como sendo algo que foi produzido pela automação, e que de certa forma gerou uma saída (output). Por exemplo, um fornecedor que foi homologado, um produto cadastrado em um determinado sistema, etc.

Durante a execução de um processo, pode ser que apenas um item de saída seja gerado ao final, ou sejam gerados múltiplos itens em uma mesma execução. Tudo isso fica a cargo das regras de negócio e do processo realizado pelo robô.

No nosso projeto de exemplo, utilizamos variáveis para contar o total de itens processados em uma execução, também separando os itens com sucesso e falha, inicializando eles com zero e somando mais um dependendo do fluxo que o processamento tomar.

# Contador de itens processados
total_itens = 0
itens_sucesso = 0
itens_falhos = 0

Após processar todos os itens disponiveis no Datapool, reportamos as informações completas na finalização de tarefa, seus status, mensagem de finalização e reporte de itens.

É importante que a contagem dos itens seja reportada como no exemplo:

# Finalizando a tarefa e reportando os itens processados
maestro.finish_task(
    task_id=execution.task_id,
    status=status,
    message=message,
    total_items=total_itens,
    processed_items=itens_sucesso,
    failed_items=itens_falhos
)

Atenção

Lembrando que a configuração e entrada de dados financeiros é essencial para serem geradas informações e indicativos relevantes referentes aos processos.

Certifique-se de que os valores de entrada utilizados estão corretos para cada Automação.