INTRODUÇÃO
Post anterior: Do Caos ao Prompt T4E03: Desenvolvimento do App AG2P – Evento "Recebeu lista de tarefas a fazer"
Este Post é o episódio 4 da temporada 5 da série "Do Caos ao Prompt", que apresenta a integração da interface do usuário com o evento "Recebeu lista de tarefas a fazer", para o Agente de Gestão de Processo Pessoal (AG2P).
Quando o post do episódio 3 da temporada 4 da série "Do Caos ao Prompt" foi criado, para implementar o evento "Recebeu lista de tarefas a fazer", ainda não existia a interface do usuário.
Portanto, este post especifica para o Chatbot de IA Gemini Google, um comando para integrar a interface do usuário com o evento "Recebeu lista de tarefas a fazer".
Comando para o Gemini
1 Objetivo
O objetivo deste comando é solicitar ao Google Gemini que escreva o código em Google Apps Script para automatizar o evento "Recebeu lista de tarefas a fazer", no app AG2P, integrado com a aba "Interface do Usuário", da planilha Google GPS.
2 Contexto
A interface com o usuário do app AG2P já está implementada pelo Gemini, na aba "Interface do Usuário", da planilha GPS, para os eventos:
- Abriu planilhas GPS
- Abriu RDM
Estão faltando estes eventos:
- Recebeu lista de tarefas a fazer
- Iniciou tarefa do negócio
- Terminou tarefa do negócio
- Ocorreu um incidente
- Executou tarefa em hora extra
- Decidiu encerrar a jornada
- Liberou RDM
- Selecionou totais para produtividade
- Selecinou incidentes por origem
- Avaliou a capacidade do processo
- Fechou RDM
Será implementado agora o evento "Recebeu lista de tarefas a fazer".
2.1 Evento
O código do evento "Recebeu lista de tarefas a fazer", já foi desenvolvido pelo Gemini, na série "Do Caos ao Prompt T4E03", mas de forma isolada, sem uma interface com o usuário.
Este comando abrange a especificação completa, ou seja, desde a interface do usuário até o evento "Recebeu lista de tarefas a fazer".
2.2 Dados da planilha GPS
Estes dados estão referenciados nos tópicos 3.1.2 Passos e 3.1.6 Regras.
2.2.1 Aba "Interface do Usuário"
- Coluna C(Situação do evento)
- Coluna D(Estado Atual)
- Coluna E(Próximo Estado)
2.2.2 Aba "RDM"
- Célula T1
- Célula A2
- Célula A4
- Célula D4
- Célula E4
- Célula F4
- Célula G4
- Célula H4
- Célula T1
2.2.3 Aba "GPS"
- Célula C6
- Coluna B(Grupo de Processos do Serviço)
- Coluna C(Tamanho em Pontos)
- Coluna E(Data Hora Início)
- Coluna R(Plano do Dia)
3 Descrição do Processo
Se o usuário disparar o evento “Recebeu lista de tarefas a fazer”;
o app responderá interagindo com o usuário para executar "3.1 Operações Plano do Dia";
o app deverá acessar os dados necessários na aba "Interface do Usuário";
o app deverá acessar os dados necessários na aba "RDM";
o app deverá acessar os dados necessários na aba "GPS";
o app deverá ter a sua operação direcionada pelas regras identificadas por
R01, R03, R04, R27, R28, R29, R30, R43,
Regra_05_FrontEnd, Regra_10_FrontEnd, Regra_11_FrontEnd,
Regra_01_GPS, Regra_02_GPS, Regra_03_GPS, Regra_04_GPS, Regra_05_GPS,
Regra_06_GPS".
3.1 Operações Plano do Dia
3.1.1 Preparação e Informações Necessárias
- O usuário deve ter a lista de tarefas a fazer no dia, as prioridades e a meta do dia definidas.
- O estado atual da aba RDM deve estar igual a "RDM Inicializada".
3.1.2 Passos
Passo 1: O usuário deve selecionar "EVENTO EM EXECUÇÃO" para o evento "Recebeu lista de tarefas a executar" na coluna C(Situação do evento) da aba "Interface do Usuário", conforme a Regra_05_FrontEnd.
Passo 2: O app AG2P deve registrar "EVENTO EXECUTADO" para o evento "Recebeu lista de tarefas a executar" na coluna C(Situação do evento) da aba "Interface do Usuário", e, na mesma aba, "RDM Inicializada" na coluna D(Estado Atual) (Regra_10_FrontEnd) e "RDM Ativa" na coluna E(Próximo Estado) (Regra_11_FrontEnd).
Passo 3: O app AG2P deve registrar "RDM Ativa" na célula T1 da aba RDM.
Passo 4: O app AG2P deve registrar, na aba GPS, a data e hora atual, na célula C6 (PLANEJADO), se a célula estiver vazia.
Passo 5: O app AG2P deve registrar, na aba RDM, a data atual, na célula A2 (PLANEJADO).
Passo 6: O app AG2P deve registrar, na aba RDM, a hora de início da jornada, na célula A4 (Hora), do grupo de colunas PLANEJADO. (R01)
Passo 7: O app AG2P deve apresentar ao usuário a lista de a tarefas a fazer, selecionando na aba GPS, na coluna B(Grupo de Processos do Serviço), aquelas que tiverem na coluna C(Tamanho em Pontos) um valor maior que zero e na coluna E(Data Hora Início), nenhum valor.
Passo 8: O usuário deve selecionar as tarefas a fazer no dia, que foram apresentadas pelo app, de acordo com a prioridade.(R27)
Passo 9: O usuário deve atribuir o tamanho de cada tarefa a fazer, se já não tiver atribuído.(R03, R04, R28)
Passo 10: O app AG2P deve copiar a data de hoje, que está registrada na aba RDM, na célula A2 (PLANEJADO), para a aba GPS, na coluna R(Plano do Dia), na mesma linha da tarefa a fazer selecionada pelo usuário.
Passo 11: O agente AG2P deve calcular o total de pontos das tarefas selecionadas pelo usuário, por fase do processo, usando o código estruturado da tarefa para descobrir a que fase cada tarefa pertence.(R29, Regra_01_GPS, Regra_02_GPS, Regra_03_GPS, Regra_04_GPS, Regra_05_GPS, Regra_06_GPS)
Passo 12: O agente AG2P deve registrar o total de pontos calculado de cada fase do processo, na aba RDM, na linha 4, nas colunas D(Iniciação), E(Planejamento), F(Execução), G(Monitoramento) e H(Encerramento). (R01, R30)
Passo 13: O agente AG2P deve atualizar o estado da aba RDM para "RDM Ativa", na célula T1. (R43)
3.1.3 Resultados Esperados
- Na aba RDM, as células D4 a H4 devem estar atualizadas com a meta do dia por fase do processo (total de pontos).
- Na aba GPS, a célula C6 deve conter a data e hora atual, se for o primeiro Plano do Dia realizado, no período de execução do serviço.
- Na aba RDM, a célula A2 deve conter a data atual.
- Na aba RDM, a célula A4 deve conter a hora de início da jornada.
- Na aba RDM, a célula T1 deve conter o estado "RDM Ativa".
3.1.4 Ações em caso de problema
- Agir conforme as mensagens de alerta do app a respeito do problema.
- Revisar o que foi feito até a ocorrência do problema.
- Solicitar ajuda à pessoa responsável pelo Suporte na Organização, se não for possível tomar ações corretivas.
3.1.5 Atenção especial
- Atenção especial para as tarefas pendentes há mais de 2 dias, para avaliar se entram no Plano do Dia ou não.
- Atenção especial para o cálculo do total de pontos por fase do processo, pois esse cálculo usa o código estruturado da tarefa como referência, que é padronizado.
- O estado da aba RDM deve estar igual a "RDM Ativa", após o final do evento.
3.1.6 Regras
R01: A jornada diária deve ter a duração máxima de 9 horas por dia, sem hora fixa para começar e terminar, desde que o início e o término sejam na mesma data.
R03: A meta do dia deve ser definida por decisão arbitrária do usuário, considerando seu conhecimento e experiência no processo pessoal, se não existirem dados históricos de, pelo menos, 30 dias, no gráfico XmR, para referência.
R04: A meta do dia deve ser definida com base na capacidade do processo pessoal, se existirem dados históricos de, no mínimo, 30 dias, no gráfico XmR.
R27: Para cada tarefa a fazer no dia deve ser atribuída a prioridade definida pelo(a) gestor(a).
R28: Para cada tarefa a fazer no dia deve ser atribuída a fase e o tamanho, conforme o Grupo de Processos do Serviço (GPS).
R29: O somatório dos totais de pontos das fases a fazer não pode ultrapassar em mais de 10% a meta definida nas regras R03 e R04.
R30: Os totais de pontos das fases a fazer devem ser registrados na aba RDM, na linha 4, nas colunas D(Iniciação), E(Planejamento), F(Execução), G(Monitoramento) e H(Encerramento).
R43: O evento "Recebeu lista de tarefas a fazer" deve mudar o estado da RDM de "RDM Inicializada" para "RDM ativa".
Regra_05_FrontEnd: A coluna situação do evento deve conter uma destas 3 opções: EVENTO PLANEJADO, EVENTO EM EXECUÇÃO ou EVENTO EXECUTADO.
Regra_10_FrontEnd: O estado atual para o evento "Recebeu lista de tarefas a fazer" deve ser igual a "RDM Inicializada", na aba "Interface do Usuário".
Regra_11_FrontEnd: O próximo estado para o evento "Recebeu lista de tarefas a fazer" deve ser igual a "RDM Ativa", na aba "Interface do Usuário".
Regra_01_GPS: O Serviço (nível 1 da hierarquia) deve ser identificado com o seguinte formato:
Serviço: Sxx nome, sendo
- "Serviço: S" constante,
- "xx" um inteiro
- "xx" um inteiro de 2 dígitos, variando de 0 a 99 (com zero à esquerda), e
- "nome" um texto que identifique o serviço.
Regra_02_GPS: A Fase (nível 2 da hierarquia) de um Serviço Sxx deve ser identificada por um desses nomes, sendo xx atribuído conforme a Regra_01_GPS:
- Sxx.1 Iniciação,
- Sxx.2 Planejamento,
- Sxx.3 Execução,
- Sxx.4 Monitoramento,
- Sxx.5 Encerramento.
Regra_03_GPS: O Subprocesso (nível 3 da hierarquia) de uma Fase f de um Serviço Sxx deve ter esses três grupos de Tarefas Executáveis, sendo xx atribuído conforme a Regra_01_GPS e f atribuído conforme a Regra_02_GPS:
- Sxx.f.1 Entrada,
- Sxx.f.2 Processamento,
- Sxx.f.3 Saída.
Exemplo de Subprocessos para Fase 1 de um Serviço S01:
- S01.1.1 Entrada,
- S01.1.2 Processamento,
- S01.1.3 Saída.
Regra_04_GPS: A Tarefa Executável (nível 4 da hierarquia) de um Subprocesso de uma Fase f de um Serviço Sxx deve ser uma frase com sujeito, que tenha o sentido de obrigar, proibir ou restringir, com um desses formatos, respectivamente, , sendo xx atribuído conforme a Regra_01_GPS, f atribuído conforme a Regra_02_GPS e n atribuído conforem a Regra_03_GPS:
- "Sxx.f.n.1.01 "...deve..." ou "...não pode..." ou "...pode..., somente se...".
Exemplo de Tarefa Executável de um Subprocesso 1 de uma Fase 1 de um Serviço S01:
- S01.1.1.01 Um pedido deve ter uma verificação de crédito.
- S01.1.1.02 Um produto não pode ser vendido a um risco de crédito ruim.
- S01.1.1.03 Um pedido pode ser dispensado da verificação de crédito, somente se o valor total for inferior 100 unidades monetárias.
Regra_05_GPS: O tamanho de uma Tarefa Executável deve ser estimado em Pontos, com uma abordagem que utiliza TShirt Size combinada com Série de Fibonacci ajustada, conforme a tabela abaixo:
- TShirt Size => Série de Fibonacci ajustada
- Muito Pequeno=PP => 1 ou 2
- Pequeno=P => 3 ou 5
- Médio=M => 8 ou 13
- Grande=G => 21 ou 34
- Muito Grande=GG => 55 ou 100
Regra_06_GPS: O tamanho total de uma Fase deve ser calculado como o somatório dos pontos das Tarefas Executáveis pertencentes à mesma.
Regra_07_GPS: A estrutura hierárquica do Grupo de Processos do Serviço deve ser armazenada na aba GPS, na coluna B(Grupo de Processos do Serviço).
Regra_08_GPS: O tamanho em pontos de cada Tarefa Executável deve ser armazenado na aba GPS, na coluna C(Tamanho em Pontos).
4 Comando para o Gemini
Faça o código no Apps Script para implementar o evento "Recebeu lista de tarefas a fazer" conforme as especificações acima.
Continue usando a estrutura da planilha GPS e faça os ajustes necessários no script que fez a implementação dos eventos "Abriu planilhas GPS" e "Abriu RDM".
5 Resposta do Gemini
Com certeza! Vamos integrar o evento "Recebeu lista de tarefas a fazer" ao seu aplicativo AG2P, atualizando o script existente. O objetivo é automatizar o fluxo de trabalho do "Plano do Dia" e garantir que a interface do usuário na planilha GPS seja atualizada corretamente.
Atualizações no Código Google Apps Script
Vamos ajustar o código que você já tem para incluir a nova funcionalidade. As principais mudanças serão:
- Adicionar uma nova função
recebeuListaDeTarefasAFazer(): Esta será a função principal para o novo evento.
- Modificar a função
onOpen(): Para incluir o novo item de menu.
- Implementar a lógica dos 13 passos: Dentro da nova função, lidaremos com a interação com as abas "Interface do Usuário", "RDM" e "GPS", aplicando as regras especificadas.
- Funções auxiliares: Poderemos adicionar ou modificar funções auxiliares para facilitar o acesso aos dados da planilha GPS, como a identificação de fases das tarefas.
Código Google Apps Script (Atualizado)
Abra o seu editor de Apps Script (Extensões > Apps Script) na sua planilha GPS, apague o código existente e cole este novo código:
const NOME_ABA_INTERFACE_USUARIO = "Interface do Usuário";
const NOME_ABA_RDM = "RDM";
const NOME_ABA_GPS = "GPS";
const EVENTO_PLANEJADO = "EVENTO PLANEJADO";
const EVENTO_EM_EXECUCAO = "EVENTO EM EXECUÇÃO";
const EVENTO_EXECUTADO = "EVENTO EXECUTADO";
const CELULA_RDM_ESTADO = "T1";
const CELULA_RDM_DATA_ATUAL = "A2";
const CELULA_RDM_HORA_INICIO_JORNADA = "A4";
const CELULA_GPS_DATA_HORA_PLANEJADO = "C6";
const COL_EVENTO_UI = 2;
const COL_SITUACAO_UI = 3;
const COL_ESTADO_ATUAL_UI = 4;
const COL_PROXIMO_ESTADO_UI = 5;
const COL_GPS_GRUPO_PROCESSOS = 2;
const COL_GPS_TAMANHO_PONTOS = 3;
const COL_GPS_DATA_HORA_INICIO = 5;
const COL_GPS_PLANO_DO_DIA = 18;
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('AG2P - Jornada')
.addItem('Iniciar Jornada (Abriu planilhas GPS)', 'abriuPlanilhasGPS')
.addItem('Iniciar Jornada (Abriu RDM)', 'abriuRDM')
.addItem('Fazer Plano do Dia (Recebeu lista de tarefas a fazer)', 'recebeuListaDeTarefasAFazer')
.addSeparator()
.addItem('Verificar Situação (Fechou RDM)', 'verificarSituacaoFechouRDM')
.addSeparator()
.addItem('Resetar Situação dos Eventos', 'resetEventSituations')
.addToUi();
}
function abriuPlanilhasGPS() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ui = SpreadsheetApp.getUi();
const interfaceUsuarioSheet = ss.getSheetByName(NOME_ABA_INTERFACE_USUARIO);
const rdmSheet = ss.getSheetByName(NOME_ABA_RDM);
if (!interfaceUsuarioSheet || !rdmSheet) {
ui.alert("Erro", "As abas '" + NOME_ABA_INTERFACE_USUARIO + "' ou '" + NOME_ABA_RDM + "' não foram encontradas. Verifique os nomes.", ui.ButtonSet.OK);
return;
}
const rangeFechouRDM = findEventRow(interfaceUsuarioSheet, "Fechou RDM");
if (!rangeFechouRDM) {
ui.alert("Erro", "O evento 'Fechou RDM' não foi encontrado na aba '" + NOME_ABA_INTERFACE_USUARIO + "'.", ui.ButtonSet.OK);
return;
}
const rowFechouRDM = rangeFechouRDM.getRow();
const situacaoFechouRDM = interfaceUsuarioSheet.getRange(rowFechouRDM, COL_SITUACAO_UI).getValue();
const estadoRDM = rdmSheet.getRange(CELULA_RDM_ESTADO).getValue();
if (situacaoFechouRDM !== EVENTO_EXECUTADO || estadoRDM !== "RDM Fechada") {
ui.alert(
"Alerta",
"Condições para iniciar a jornada não atendidas:\n- 'Fechou RDM' não está 'EVENTO EXECUTADO' ou\n- RDM (célula " + CELULA_RDM_ESTADO + ") não está 'RDM Fechada'.\n\nAbrindo a aba 'Interface do Usuário' para revisão.",
ui.ButtonSet.OK
);
interfaceUsuarioSheet.activate();
return;
}
const rangeAbriuPlanilhasGPS = findEventRow(interfaceUsuarioSheet, "Abriu planilhas GPS");
if (!rangeAbriuPlanilhasGPS) {
ui.alert("Erro", "O evento 'Abriu planilhas GPS' não foi encontrado na aba '" + NOME_ABA_INTERFACE_USUARIO + "'.", ui.ButtonSet.OK);
return;
}
const rowAbriuPlanilhasGPS = rangeAbriuPlanilhasGPS.getRow();
interfaceUsuarioSheet.getRange(rowAbriuPlanilhasGPS, COL_SITUACAO_UI).setValue(EVENTO_EM_EXECUCAO);
interfaceUsuarioSheet.getRange(rowAbriuPlanilhasGPS, COL_SITUACAO_UI).setValue(EVENTO_EXECUTADO);
interfaceUsuarioSheet.getRange(rowAbriuPlanilhasGPS, COL_ESTADO_ATUAL_UI).setValue("N/a");
interfaceUsuarioSheet.getRange(rowAbriuPlanilhasGPS, COL_PROXIMO_ESTADO_UI).setValue("Após início");
SpreadsheetApp.flush();
ui.alert("Sucesso", "Evento 'Abriu planilhas GPS' executado com sucesso.\nAgora, por favor, execute o evento 'Abriu RDM' para continuar a jornada.", ui.ButtonSet.OK);
}
function abriuRDM() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ui = SpreadsheetApp.getUi();
const interfaceUsuarioSheet = ss.getSheetByName(NOME_ABA_INTERFACE_USUARIO);
const rdmSheet = ss.getSheetByName(NOME_ABA_RDM);
if (!interfaceUsuarioSheet || !rdmSheet) {
ui.alert("Erro", "As abas '" + NOME_ABA_INTERFACE_USUARIO + "' ou '" + NOME_ABA_RDM + "' não foram encontradas. Verifique os nomes.", ui.ButtonSet.OK);
return;
}
const rangeAbriuRDM = findEventRow(interfaceUsuarioSheet, "Abriu RDM");
if (!rangeAbriuRDM) {
ui.alert("Erro", "O evento 'Abriu RDM' não foi encontrado na aba '" + NOME_ABA_INTERFACE_USUARIO + "'.", ui.ButtonSet.OK);
return;
}
const rowAbriuRDM = rangeAbriuRDM.getRow();
const estadoAtualAbriuRDM_UI = interfaceUsuarioSheet.getRange(rowAbriuRDM, COL_ESTADO_ATUAL_UI).getValue();
if (estadoAtualAbriuRDM_UI !== "Após início") {
ui.alert(
"Erro",
"O evento 'Abriu RDM' não pode ser iniciado. O 'Estado Atual' esperado na '" + NOME_ABA_INTERFACE_USUARIO + "' é 'Após início'.\nCertifique-se de que o evento 'Abriu planilhas GPS' foi executado primeiro.",
ui.ButtonSet.OK
);
return;
}
const estadoRDM = rdmSheet.getRange(CELULA_RDM_ESTADO).getValue();
if (estadoRDM !== "RDM Fechada") {
ui.alert(
"Erro",
"O evento 'Abriu RDM' não pode ser iniciado. O estado atual da aba '" + NOME_ABA_RDM + "' (célula " + CELULA_RDM_ESTADO + ") esperado é 'RDM Fechada'.",
ui.ButtonSet.OK
);
return;
}
interfaceUsuarioSheet.getRange(rowAbriuRDM, COL_SITUACAO_UI).setValue(EVENTO_EM_EXECUCAO);
interfaceUsuarioSheet.getRange(rowAbriuRDM, COL_SITUACAO_UI).setValue(EVENTO_EXECUTADO);
interfaceUsuarioSheet.getRange(rowAbriuRDM, COL_ESTADO_ATUAL_UI).setValue("Após início");
interfaceUsuarioSheet.getRange(rowAbriuRDM, COL_PROXIMO_ESTADO_UI).setValue("RDM Inicializada");
rdmSheet.getRange(CELULA_RDM_ESTADO).setValue("RDM Inicializada");
const lastRow = interfaceUsuarioSheet.getLastRow();
for (let i = 2; i <= lastRow; i++) {
const eventName = interfaceUsuarioSheet.getRange(i, COL_EVENTO_UI).getValue();
if (eventName !== "Abriu planilhas GPS" && eventName !== "Abriu RDM") {
interfaceUsuarioSheet.getRange(i, COL_SITUACAO_UI).setValue(EVENTO_PLANEJADO);
interfaceUsuarioSheet.getRange(i, COL_ESTADO_ATUAL_UI).clearContent();
interfaceUsuarioSheet.getRange(i, COL_PROXIMO_ESTADO_UI).clearContent();
}
}
const rangeRecebeuLista = findEventRow(interfaceUsuarioSheet, "Recebeu lista de tarefas a fazer");
if (rangeRecebeuLista) {
const rowRecebeuLista = rangeRecebeuLista.getRow();
interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_SITUACAO_UI).setValue(EVENTO_PLANEJADO);
}
SpreadsheetApp.flush();
interfaceUsuarioSheet.activate();
ui.alert("Sucesso", "Jornada iniciada e RDM inicializada com sucesso! A aba '" + NOME_ABA_INTERFACE_USUARIO + "' está pronta para o próximo passo: 'Recebeu lista de tarefas a fazer'.", ui.ButtonSet.OK);
}
function recebeuListaDeTarefasAFazer() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ui = SpreadsheetApp.getUi();
const interfaceUsuarioSheet = ss.getSheetByName(NOME_ABA_INTERFACE_USUARIO);
const rdmSheet = ss.getSheetByName(NOME_ABA_RDM);
const gpsSheet = ss.getSheetByName(NOME_ABA_GPS);
if (!interfaceUsuarioSheet || !rdmSheet || !gpsSheet) {
ui.alert("Erro", "Uma ou mais abas ('" + NOME_ABA_INTERFACE_USUARIO + "', '" + NOME_ABA_RDM + "', '" + NOME_ABA_GPS + "') não foram encontradas. Verifique os nomes.", ui.ButtonSet.OK);
return;
}
const estadoAtualRDM = rdmSheet.getRange(CELULA_RDM_ESTADO).getValue();
if (estadoAtualRDM !== "RDM Inicializada") {
ui.alert(
"Erro",
"O evento 'Recebeu lista de tarefas a fazer' não pode ser iniciado.\nO estado atual da RDM (célula " + CELULA_RDM_ESTADO + ") deve ser 'RDM Inicializada'.",
ui.ButtonSet.OK
);
return;
}
const rangeRecebeuLista = findEventRow(interfaceUsuarioSheet, "Recebeu lista de tarefas a fazer");
if (!rangeRecebeuLista) {
ui.alert("Erro", "O evento 'Recebeu lista de tarefas a fazer' não foi encontrado na aba '" + NOME_ABA_INTERFACE_USUARIO + "'.", ui.ButtonSet.OK);
return;
}
const rowRecebeuLista = rangeRecebeuLista.getRow();
const estadoAtualRecebeuLista_UI = interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_ESTADO_ATUAL_UI).getValue();
if (estadoAtualRecebeuLista_UI !== "RDM Inicializada" && estadoAtualRecebeuLista_UI !== "") {
ui.alert(
"Erro",
"O evento 'Recebeu lista de tarefas a fazer' não pode ser iniciado.\nO 'Estado Atual' esperado na '" + NOME_ABA_INTERFACE_USUARIO + "' é 'RDM Inicializada' (Regra_10_FrontEnd).",
ui.ButtonSet.OK
);
return;
}
interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_SITUACAO_UI).setValue(EVENTO_EM_EXECUCAO);
interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_SITUACAO_UI).setValue(EVENTO_EXECUTADO);
interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_ESTADO_ATUAL_UI).setValue("RDM Inicializada");
interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_PROXIMO_ESTADO_UI).setValue("RDM Ativa");
rdmSheet.getRange(CELULA_RDM_ESTADO).setValue("RDM Ativa");
const gpsC6 = gpsSheet.getRange(CELULA_GPS_DATA_HORA_PLANEJADO);
if (gpsC6.isBlank()) {
gpsC6.setValue(new Date());
}
rdmSheet.getRange(CELULA_RDM_DATA_ATUAL).setValue(Utilities.formatDate(new Date(), SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(), "dd/MM/yyyy"));
rdmSheet.getRange(CELULA_RDM_HORA_INICIO_JORNADA).setValue(Utilities.formatDate(new Date(), SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(), "HH:mm"));
const gpsLastRow = gpsSheet.getLastRow();
const gpsData = gpsSheet.getRange(2, 1, gpsLastRow - 1, gpsSheet.getLastColumn()).getValues();
let tarefasAPresentar = [];
const colGrupoProcessos = COL_GPS_GRUPO_PROCESSOS - 1;
const colTamanhoPontos = COL_GPS_TAMANHO_PONTOS - 1;
const colDataHoraInicio = COL_GPS_DATA_HORA_INICIO - 1;
for (let i = 0; i < gpsData.length; i++) {
const row = gpsData[i];
const tamanhoEmPontos = row[colTamanhoPontos];
const dataHoraInicio = row[colDataHoraInicio];
if (tamanhoEmPontos > 0 && (dataHoraInicio === "" || dataHoraInicio === null)) {
tarefasAPresentar.push(`Linha ${i + 2} - ${row[colGrupoProcessos]} (Tamanho: ${tamanhoEmPontos} pontos)`);
}
}
if (tarefasAPresentar.length === 0) {
ui.alert("Plano do Dia", "Não há tarefas disponíveis para o plano do dia com os critérios especificados.", ui.ButtonSet.OK);
} else {
ui.alert(
"Tarefas Disponíveis para o Plano do Dia",
"As seguintes tarefas estão disponíveis:\n" + tarefasAPresentar.join("\n") + "\n\nPor favor, selecione as tarefas a fazer (Passo 8) e atribua o tamanho, se necessário (Passo 9).",
ui.ButtonSet.OK
);
}
const selectedTasksInput = ui.prompt(
"Seleção de Tarefas",
"Por favor, insira os NÚMEROS DAS LINHAS das tarefas selecionadas na aba GPS (ex: 2,5,8). Separe por vírgulas.\n" +
"Certifique-se de que o tamanho em pontos (Coluna C) esteja atualizado e a data de início (Coluna E) esteja vazia para as tarefas selecionadas.",
ui.ButtonSet.OK_CANCEL
);
if (selectedTasksInput.getSelectedButton() === ui.Button.CANCEL) {
ui.alert("Plano do Dia Cancelado", "O plano do dia foi cancelado pelo usuário.", ui.ButtonSet.OK);
return;
}
const selectedRows = selectedTasksInput.getResponseText().split(',').map(rowStr => parseInt(rowStr.trim(), 10)).filter(num => !isNaN(num) && num >= 2);
if (selectedRows.length === 0) {
ui.alert("Nenhuma Tarefa Selecionada", "Nenhuma tarefa válida foi selecionada para o plano do dia.", ui.ButtonSet.OK);
return;
}
const todayDate = rdmSheet.getRange(CELULA_RDM_DATA_ATUAL).getValue();
const colPlanoDoDia = COL_GPS_PLANO_DO_DIA;
for (const rowNum of selectedRows) {
gpsSheet.getRange(rowNum, colPlanoDoDia).setValue(todayDate);
}
const totalPontosPorFase = {
"Iniciação": 0,
"Planejamento": 0,
"Execução": 0,
"Monitoramento": 0,
"Encerramento": 0
};
const phaseKeywords = {
".1 Iniciação": "Iniciação",
".2 Planejamento": "Planejamento",
".3 Execução": "Execução",
".4 Monitoramento": "Monitoramento",
".5 Encerramento": "Encerramento"
};
const colGrupoProcessosIndex = COL_GPS_GRUPO_PROCESSOS;
const colTamanhoPontosIndex = COL_GPS_TAMANHO_PONTOS;
for (const rowNum of selectedRows) {
const grupoProcesso = gpsSheet.getRange(rowNum, colGrupoProcessosIndex).getValue();
const tamanhoPontos = parseFloat(gpsSheet.getRange(rowNum, colTamanhoPontosIndex).getValue());
if (!isNaN(tamanhoPontos) && tamanhoPontos > 0) {
let foundPhase = false;
for (const keyword in phaseKeywords) {
if (grupoProcesso.includes(keyword)) {
totalPontosPorFase[phaseKeywords[keyword]] += tamanhoPontos;
foundPhase = true;
break;
}
}
if (!foundPhase) {
ui.alert("Atenção", `Não foi possível identificar a fase para a tarefa da linha ${rowNum}: ${grupoProcesso}. Verifique o formato do 'Grupo de Processos do Serviço' (Regra_02_GPS).`, ui.ButtonSet.OK);
}
} else {
ui.alert("Atenção", `A tarefa da linha ${rowNum} (${grupoProcesso}) tem tamanho inválido ou zero. Ignorada no cálculo do plano do dia. (R03, R04, R28)`, ui.ButtonSet.OK);
}
}
const totalGeralPontos = Object.values(totalPontosPorFase).reduce((sum, current) => sum + current, 0);
ui.alert("Cálculo do Plano do Dia", `Total de pontos planejados:\nIniciação: ${totalPontosPorFase.Iniciação}\nPlanejamento: ${totalPontosPorFase.Planejamento}\nExecução: ${totalPontosPorFase.Execução}\nMonitoramento: ${totalPontosPorFase.Monitoramento}\nEncerramento: ${totalPontosPorFase.Encerramento}\n\nTotal Geral: ${totalGeralPontos} pontos.\n\nVerifique se o total geral não ultrapassa em mais de 10% a sua meta do dia (R29).`, ui.ButtonSet.OK);
rdmSheet.getRange("D4").setValue(totalPontosPorFase.Iniciação);
rdmSheet.getRange("E4").setValue(totalPontosPorFase.Planejamento);
rdmSheet.getRange("F4").setValue(totalPontosPorFase.Execução);
rdmSheet.getRange("G4").setValue(totalPontosPorFase.Monitoramento);
rdmSheet.getRange("H4").setValue(totalPontosPorFase.Encerramento);
rdmSheet.getRange(CELULA_RDM_ESTADO).setValue("RDM Ativa");
SpreadsheetApp.flush();
ui.alert("Sucesso", "O evento 'Recebeu lista de tarefas a fazer' foi concluído com sucesso! O Plano do Dia está registrado.", ui.ButtonSet.OK);
}
function findEventRow(sheet, eventName) {
const lastRow = sheet.getLastRow();
const eventColumnValues = sheet.getRange(1, COL_EVENTO_UI, lastRow, 1).getValues();
for (let i = 0; i < eventColumnValues.length; i++) {
if (eventColumnValues[i][0] === eventName) {
return sheet.getRange(i + 1, COL_EVENTO_UI);
}
}
return null;
}
function verificarSituacaoFechouRDM() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ui = SpreadsheetApp.getUi();
const interfaceUsuarioSheet = ss.getSheetByName(NOME_ABA_INTERFACE_USUARIO);
const rdmSheet = ss.getSheetByName(NOME_ABA_RDM);
if (!interfaceUsuarioSheet || !rdmSheet) {
ui.alert("Erro", "As abas '" + NOME_ABA_INTERFACE_USUARIO + "' ou '" + NOME_ABA_RDM + "' não foram encontradas. Verifique os nomes.", ui.ButtonSet.OK);
return;
}
const rangeFechouRDM = findEventRow(interfaceUsuarioSheet, "Fechou RDM");
if (!rangeFechouRDM) {
ui.alert("Erro", "O evento 'Fechou RDM' não foi encontrado na aba '" + NOME_ABA_INTERFACE_USUARIO + "'.", ui.ButtonSet.OK);
return;
}
const rowFechouRDM = rangeFechouRDM.getRow();
const situacaoFechouRDM = interfaceUsuarioSheet.getRange(rowFechouRDM, COL_SITUACAO_UI).getValue();
const estadoRDM = rdmSheet.getRange(CELULA_RDM_ESTADO).getValue();
let message = `Situação do evento 'Fechou RDM': ${situacaoFechouRDM}\nEstado da RDM (célula ${CELULA_RDM_ESTADO}): ${estadoRDM}`;
if (situacaoFechouRDM === EVENTO_EXECUTADO && estadoRDM === "RDM Fechada") {
message += "\nAs condições para iniciar a jornada são atendidas (pronto para 'Abriu planilhas GPS').";
} else {
message += "\nAs condições para iniciar a jornada NÃO são atendidas. Por favor, certifique-se de que a jornada anterior foi encerrada corretamente.";
}
ui.alert("Verificação de Situação", message, ui.ButtonSet.OK);
}
function resetEventSituations() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ui = SpreadsheetApp.getUi();
const interfaceUsuarioSheet = ss.getSheetByName(NOME_ABA_INTERFACE_USUARIO);
const rdmSheet = ss.getSheetByName(NOME_ABA_RDM);
const gpsSheet = ss.getSheetByName(NOME_ABA_GPS);
if (!interfaceUsuarioSheet) {
ui.alert("Erro", "A aba '" + NOME_ABA_INTERFACE_USUARIO + "' não foi encontrada. Verifique o nome.", ui.ButtonSet.OK);
return;
}
const lastRow = interfaceUsuarioSheet.getLastRow();
for (let i = 2; i <= lastRow; i++) {
interfaceUsuarioSheet.getRange(i, COL_SITUACAO_UI).setValue(EVENTO_PLANEJADO);
interfaceUsuarioSheet.getRange(i, COL_ESTADO_ATUAL_UI).clearContent();
interfaceUsuarioSheet.getRange(i, COL_PROXIMO_ESTADO_UI).clearContent();
}
if (rdmSheet) {
rdmSheet.getRange(CELULA_RDM_ESTADO).setValue("RDM Fechada");
rdmSheet.getRange(CELULA_RDM_DATA_ATUAL).clearContent();
rdmSheet.getRange(CELULA_RDM_HORA_INICIO_JORNADA).clearContent();
rdmSheet.getRange("D4:H4").clearContent();
}
if (gpsSheet) {
gpsSheet.getRange(CELULA_GPS_DATA_HORA_PLANEJADO).clearContent();
}
ui.alert("Sucesso", "Todas as situações dos eventos na aba '" + NOME_ABA_INTERFACE_USUARIO + "' foram resetadas para 'EVENTO PLANEJADO', RDM para 'RDM Fechada' e dados relevantes limpos.", ui.ButtonSet.OK);
}
Como Usar o Script (Instruções Atualizadas)
- Cole o Código: Certifique-se de que a planilha, as abas ("Interface do Usuário", "RDM", "GPS") e as validações de dados (Coluna C na "Interface do Usuário") já estão configuradas conforme o esperado. Abra o editor de Apps Script (Extensões > Apps Script), apague qualquer código existente e cole o código fornecido acima.
- Salve o Projeto: Clique no ícone de disquete (Salvar projeto).
- Autorize o Script (Somente na Primeira Vez):
- Clique no botão "Executar" (ícone de play) na barra de ferramentas do editor de script (você pode selecionar
onOpen no seletor de funções).
- Siga os passos para revisar e permitir as permissões solicitadas pelo script para acessar e modificar sua planilha.
- Execute as Funções:
- Atualize a Planilha: Volte para sua planilha Google Sheets. Você verá o menu "AG2P - Jornada" na barra de menus. Se não aparecer imediatamente, atualize a página do navegador (F5).
- Para iniciar a jornada e fazer o plano do dia, siga esta sequência:
- Pré-condição: Certifique-se de que a célula T1 na aba RDM está com o valor "RDM Fechada" e que o evento "Fechou RDM" na aba "Interface do Usuário" (Coluna B) tem sua Situação (Coluna C) como "EVENTO EXECUTADO". Use o
Resetar Situação dos Eventos se precisar limpar o ambiente.
- Clique em AG2P - Jornada > Iniciar Jornada (Abriu planilhas GPS).
- Após a conclusão do "Abriu planilhas GPS", clique em AG2P - Jornada > Iniciar Jornada (Abriu RDM).
- Finalmente, clique em AG2P - Jornada > Fazer Plano do Dia (Recebeu lista de tarefas a fazer). Este comando irá:
- Validar o estado da RDM e da interface do usuário.
- Atualizar a situação do evento "Recebeu lista de tarefas a fazer" para "EM EXECUÇÃO" e depois para "EXECUTADO".
- Preencher a data e hora em GPS C6 (se vazia), a data atual em RDM A2 e a hora atual em RDM A4.
- Apresentar as tarefas elegíveis para o plano do dia em um pop-up.
- Solicitar as linhas das tarefas que o usuário selecionou para o plano do dia.
- Copiar a data de hoje para a Coluna R (Plano do Dia) para as tarefas selecionadas.
- Calcular e registrar os totais de pontos por fase (Iniciação, Planejamento, Execução, Monitoramento, Encerramento) nas células D4:H4 da RDM.
- Atualizar o estado da RDM (T1) para "RDM Ativa".
- Para verificar o estado do evento "Fechou RDM": Clique em AG2P - Jornada > Verificar Situação (Fechou RDM).
- Para resetar o ambiente para um novo teste: Clique em AG2P - Jornada > Resetar Situação dos Eventos. Isso definirá a situação de todos os eventos na aba "Interface do Usuário" para "EVENTO PLANEJADO", a célula T1 da aba "RDM" para "RDM Fechada", e limpará outras células de data/hora relevantes.
Pontos de Atenção e Como Lidar com Eles
- R29 (Meta do Dia): O script calcula o total de pontos por fase, mas a validação de que o somatório não ultrapassa em mais de 10% a meta diária (R29) não é totalmente automatizada neste script, pois a "meta definida" (R03, R04) é algo que o usuário define arbitrariamente ou baseada em dados históricos, e não está diretamente presente como um valor configurável dentro deste fluxo automatizado. O script informa o total geral para que o usuário faça essa checagem manual. Para automatizar isso, precisaríamos de um campo para a meta diária e a lógica para calculá-la ou obtê-la.
- R27, R28 (Seleção de Tarefas e Atribuição de Tamanho/Fase): Esses passos dependem da interação e decisão do usuário. O script apresenta as tarefas e pede as linhas selecionadas, mas o usuário é responsável por "selecionar" as prioridades e "atribuir o tamanho/fase" (se ainda não tiver sido feito) na própria planilha antes de informar as linhas ao script.
- Regras GPS (R01 a R08_GPS): As regras sobre a estrutura do Grupo de Processos do Serviço (Sxx.f.n.e.01 etc.) são usadas pelo script para extrair a fase da tarefa e somar os pontos corretamente. É crucial que o formato na Coluna B da aba GPS esteja aderente a essas regras para que o cálculo seja preciso. Erros no formato podem levar a fases não identificadas.
Este código integra de forma robusta o evento "Recebeu lista de tarefas a fazer" e avança significativamente na automação do seu aplicativo AG2P.
Você gostaria de implementar os próximos eventos, como "Iniciou tarefa do negócio"?
Conclusão
Neste episódio 4, da temporada 5 da série "Do Caos ao Prompt", foi apresentada a implementação
do Evento "Recebeu lista de tarefas a fazer", realizada pelo Chatbot de IA Gemini 2.0 Flash.
Teste do app AG2P: Falhou
O app AG2P emitiu esta mensagem: "Não foi possível identificar a fase para a tarefa da linha ... . Verifique o formato do 'Grupo de Processos do Serviço' (Regra_02_GPS)."
Constatei que foi um erro meu, na especificação da Regra_02_GPS, pois faltou a definição do código "Sxx", já corrigido nest post.
No próximo Post serão apresentadas as interações com o Gemini, para ajustes no código, após a correção que fiz na Regra_02_GPS.
Correção da falha na especificação
Veja a lista de Episódios da Temporada 5 da Série "Do Caos ao Prompt", no final do Episódio
T5E01.