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).
Comando para o Gemini
1 Objetivo
2 Contexto
- Abriu planilhas GPS
- Abriu RDM
- 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
2.1 Evento
2.2 Dados da planilha GPS
- Coluna C(Situação do evento)
- Coluna D(Estado Atual)
- Coluna E(Próximo Estado)
- 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
- 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 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.
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".
- "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.
- Sxx.1 Iniciação,
- Sxx.2 Planejamento,
- Sxx.3 Execução,
- Sxx.4 Monitoramento,
- Sxx.5 Encerramento.
- Sxx.f.1 Entrada,
- Sxx.f.2 Processamento,
- Sxx.f.3 Saída.
- S01.1.1 Entrada,
- S01.1.2 Processamento,
- S01.1.3 Saída.
- "Sxx.f.n.1.01 "...deve..." ou "...não pode..." ou "...pode..., somente se...".
- 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.
- 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
4 Comando para o Gemini
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:
/**
* Variáveis globais para facilitar o acesso às abas e dados.
*/
const NOME_ABA_INTERFACE_USUARIO = "Interface do Usuário";
const NOME_ABA_RDM = "RDM";
const NOME_ABA_GPS = "GPS"; // Nova constante para a aba GPS
// Constantes para as situações dos eventos (Regra_05_FrontEnd)
const EVENTO_PLANEJADO = "EVENTO PLANEJADO";
const EVENTO_EM_EXECUCAO = "EVENTO EM EXECUÇÃO";
const EVENTO_EXECUTADO = "EVENTO EXECUTADO";
// Constantes para células específicas
const CELULA_RDM_ESTADO = "T1";
const CELULA_RDM_DATA_ATUAL = "A2"; // Célula A2 na RDM para data atual
const CELULA_RDM_HORA_INICIO_JORNADA = "A4"; // Célula A4 na RDM para hora de início da jornada
const CELULA_GPS_DATA_HORA_PLANEJADO = "C6"; // Célula C6 na GPS para data/hora planejado
// Colunas na aba "Interface do Usuário"
const COL_EVENTO_UI = 2; // Coluna B
const COL_SITUACAO_UI = 3; // Coluna C
const COL_ESTADO_ATUAL_UI = 4; // Coluna D
const COL_PROXIMO_ESTADO_UI = 5; // Coluna E
// Colunas na aba "GPS"
const COL_GPS_GRUPO_PROCESSOS = 2; // Coluna B
const COL_GPS_TAMANHO_PONTOS = 3; // Coluna C
const COL_GPS_DATA_HORA_INICIO = 5; // Coluna E
const COL_GPS_PLANO_DO_DIA = 18; // Coluna R
/**
* Função que é executada automaticamente quando a planilha é aberta.
* Cria um menu personalizado na planilha para facilitar a interação com os eventos.
*/
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') // Novo item de menu
.addSeparator()
.addItem('Verificar Situação (Fechou RDM)', 'verificarSituacaoFechouRDM')
.addSeparator()
.addItem('Resetar Situação dos Eventos', 'resetEventSituations')
.addToUi();
}
/**
* Simula o evento "Abriu planilhas GPS" disparado pelo usuário.
* Este é o primeiro evento na sequência de "Iniciar a jornada".
*/
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);
// Validação inicial das abas
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;
}
// Ação "Verificar situação do evento 'Fechou RDM'" (Regra_04_FrontEnd)
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(); // Coluna C (Situação do Evento)
const estadoRDM = rdmSheet.getRange(CELULA_RDM_ESTADO).getValue(); // Célula T1 da aba RDM
// Fluxo Alternativo: Abre a aba "Interface do Usuário" se as condições iniciais não forem atendidas
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;
}
// --- Passos do Diálogo (Assumindo que as condições iniciais foram atendidas) ---
// Passo 1: O Usuário "seleciona" EVENTO EM EXECUÇÃO para "Abriu planilhas GPS"
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); // Coluna C (Situação do Evento)
// Passo 2: O agente AG2P atualiza o estado do evento "Abriu planilhas GPS"
interfaceUsuarioSheet.getRange(rowAbriuPlanilhasGPS, COL_SITUACAO_UI).setValue(EVENTO_EXECUTADO); // Coluna C (Situação)
interfaceUsuarioSheet.getRange(rowAbriuPlanilhasGPS, COL_ESTADO_ATUAL_UI).setValue("N/a"); // Coluna D (Estado Atual) - Regra_02_FrontEnd
interfaceUsuarioSheet.getRange(rowAbriuPlanilhasGPS, COL_PROXIMO_ESTADO_UI).setValue("Após início"); // Coluna E (Próximo Estado) - Regra_03_FrontEnd
SpreadsheetApp.flush(); // Garante que as mudanças sejam aplicadas imediatamente
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);
}
/**
* Simula o evento "Abriu RDM" disparado pelo usuário.
* Este é o segundo evento na sequência de "Iniciar a jornada".
*/
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);
// Validação inicial das abas
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();
// Validação do Estado Atual na Interface do Usuário (Regra_08_FrontEnd)
const estadoAtualAbriuRDM_UI = interfaceUsuarioSheet.getRange(rowAbriuRDM, COL_ESTADO_ATUAL_UI).getValue(); // Coluna D
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;
}
// Validação do Estado Atual na aba RDM (Regra_06_FrontEnd)
const estadoRDM = rdmSheet.getRange(CELULA_RDM_ESTADO).getValue(); // Célula T1
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;
}
// --- Passos do Diálogo ---
// Passo 3: O Usuário "seleciona" EVENTO EM EXECUÇÃO para "Abriu RDM"
interfaceUsuarioSheet.getRange(rowAbriuRDM, COL_SITUACAO_UI).setValue(EVENTO_EM_EXECUCAO); // Coluna C
// Passo 4: O agente AG2P atualiza o estado do evento "Abriu RDM"
interfaceUsuarioSheet.getRange(rowAbriuRDM, COL_SITUACAO_UI).setValue(EVENTO_EXECUTADO); // Coluna C (Situação)
interfaceUsuarioSheet.getRange(rowAbriuRDM, COL_ESTADO_ATUAL_UI).setValue("Após início"); // Coluna D (Estado Atual) - Regra_08_FrontEnd
interfaceUsuarioSheet.getRange(rowAbriuRDM, COL_PROXIMO_ESTADO_UI).setValue("RDM Inicializada"); // Coluna E (Próximo Estado) - Regra_09_FrontEnd
// Passo 5: O agente AG2P registra "RDM Inicializada" na aba RDM, célula T1 (Regra_07_FrontEnd)
rdmSheet.getRange(CELULA_RDM_ESTADO).setValue("RDM Inicializada");
// Passo 6: O agente AG2P define "EVENTO PLANEJADO" para todos os eventos, exceto "Abriu planilhas GPS" e "Abriu RDM"
const lastRow = interfaceUsuarioSheet.getLastRow();
for (let i = 2; i <= lastRow; i++) { // Começa da linha 2
const eventName = interfaceUsuarioSheet.getRange(i, COL_EVENTO_UI).getValue(); // Coluna B (Evento)
if (eventName !== "Abriu planilhas GPS" && eventName !== "Abriu RDM") {
interfaceUsuarioSheet.getRange(i, COL_SITUACAO_UI).setValue(EVENTO_PLANEJADO); // Coluna C (Situação)
interfaceUsuarioSheet.getRange(i, COL_ESTADO_ATUAL_UI).clearContent(); // Limpa D
interfaceUsuarioSheet.getRange(i, COL_PROXIMO_ESTADO_UI).clearContent(); // Limpa E
}
}
// Passo 7: O agente AG2P "desabilita" células da coluna C(Situação do evento) para "EVENTO PLANEJADO",
// exceto "Recebeu lista de tarefas a fazer".
// A "desabilitação" visual (para o usuário não poder clicar) não é feita via Apps Script.
// A validação de dados já existe. O script se baseia em não alterar essas células.
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); // Garante que esteja PLANEJADO
// Opcionalmente, pode-se proteger o intervalo das outras células se desejar desabilitar a edição manual.
// Ex: interfaceUsuarioSheet.protect().setUnprotectedRanges([interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_SITUACAO_UI)]);
}
SpreadsheetApp.flush(); // Garante que todas as mudanças sejam aplicadas antes de ativar a aba
// Passo 8: O agente AG2P apresenta a aba “Interface do Usuário” ao usuário
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);
}
/**
* Implementa o evento "Recebeu lista de tarefas a fazer".
* Automa o processo de "Plano do Dia" na planilha GPS.
*/
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); // Referência à aba GPS
// Validação inicial das abas
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;
}
// Validação: Preparação e Informações Necessárias - Estado atual da RDM (T1) deve ser "RDM Inicializada"
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;
}
// Validação do Estado Atual na Interface do Usuário (Regra_10_FrontEnd)
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 !== "") { // Permite iniciar se estiver vazio, considerando um possível reset
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;
}
// --- Passos do Diálogo ---
// Passo 1: O usuário seleciona "EVENTO EM EXECUÇÃO" (Regra_05_FrontEnd)
interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_SITUACAO_UI).setValue(EVENTO_EM_EXECUCAO);
// Passo 2: O app AG2P registra "EVENTO EXECUTADO" e atualiza Estado Atual/Próximo Estado (Regra_10_FrontEnd, Regra_11_FrontEnd)
interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_SITUACAO_UI).setValue(EVENTO_EXECUTADO);
interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_ESTADO_ATUAL_UI).setValue("RDM Inicializada"); // Regra_10_FrontEnd
interfaceUsuarioSheet.getRange(rowRecebeuLista, COL_PROXIMO_ESTADO_UI).setValue("RDM Ativa"); // Regra_11_FrontEnd
// Passo 3: O app AG2P registra "RDM Ativa" na célula T1 da aba RDM (R43)
rdmSheet.getRange(CELULA_RDM_ESTADO).setValue("RDM Ativa");
// Passo 4: O app AG2P registra data e hora atual na C6 da aba GPS, se vazia
const gpsC6 = gpsSheet.getRange(CELULA_GPS_DATA_HORA_PLANEJADO);
if (gpsC6.isBlank()) {
gpsC6.setValue(new Date());
}
// Passo 5: O app AG2P registra data atual na célula A2 da aba RDM
rdmSheet.getRange(CELULA_RDM_DATA_ATUAL).setValue(Utilities.formatDate(new Date(), SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(), "dd/MM/yyyy"));
// Passo 6: O app AG2P registra hora de início da jornada na célula A4 da aba RDM (R01)
rdmSheet.getRange(CELULA_RDM_HORA_INICIO_JORNADA).setValue(Utilities.formatDate(new Date(), SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(), "HH:mm"));
// Passo 7: O app AG2P apresenta a lista de tarefas a fazer
// Seleciona na aba GPS: Coluna B (Grupo de Processos), C (Tamanho > 0), E (Data Hora Início vazia)
const gpsLastRow = gpsSheet.getLastRow();
const gpsData = gpsSheet.getRange(2, 1, gpsLastRow - 1, gpsSheet.getLastColumn()).getValues(); // Ignora cabeçalho
let tarefasAPresentar = [];
// Mapeamento das colunas para facilitar a leitura
const colGrupoProcessos = COL_GPS_GRUPO_PROCESSOS - 1; // Ajuste para índice 0-based
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
);
}
// Passo 8: Usuário deve selecionar as tarefas a fazer no dia, de acordo com a prioridade (R27)
// Passo 9: Usuário deve atribuir o tamanho de cada tarefa, se já não tiver atribuído (R03, R04, R28)
// Estes passos são interações manuais do usuário com a planilha. O script não os automatiza diretamente aqui,
// mas espera que o usuário faça isso.
// O script precisará da entrada do usuário para saber quais tarefas foram selecionadas e seus tamanhos
// para os próximos passos (10, 11 e 12).
// Para fins de automação, faremos uma solicitação de entrada simples ao usuário ou
// você pode ter um mecanismo mais robusto (ex: Sidebars, formulários customizados).
// Para este exemplo, vamos pedir as linhas das tarefas selecionadas.
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;
}
// Passo 10: Copiar data de hoje (RDM A2) para GPS Coluna R (Plano do Dia) das tarefas selecionadas
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);
}
// Passo 11: Calcular o total de pontos das tarefas selecionadas, por fase do processo (R29, Regra_01_GPS a Regra_06_GPS)
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; // Coluna B
const colTamanhoPontosIndex = COL_GPS_TAMANHO_PONTOS; // Coluna C
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) {
// Extrair a fase do código estruturado (Regra_02_GPS)
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);
}
}
// Verificar R29 (somatório dos totais de pontos não pode ultrapassar 10% da meta)
// A meta do dia (R03, R04) não está definida no script, assumimos que o usuário a define manualmente ou que será implementada depois.
// Por enquanto, esta validação (R29) será uma mensagem informativa, pois a "meta definida" não está no escopo atual.
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);
// Passo 12: Registrar o total de pontos calculado de cada fase na aba RDM, linha 4 (R01, R30)
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);
// Passo 13: Atualizar o estado da aba RDM para "RDM Ativa" na célula T1 (R43)
// Já foi feito no Passo 3. Reforçado aqui para clareza da regra.
rdmSheet.getRange(CELULA_RDM_ESTADO).setValue("RDM Ativa");
SpreadsheetApp.flush(); // Garante que todas as mudanças sejam aplicadas
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);
}
/**
* Função auxiliar para encontrar a linha de um evento específico na aba "Interface do Usuário".
* @param {GoogleAppsScript.Spreadsheet.Sheet} sheet A aba "Interface do Usuário".
* @param {string} eventName O nome do evento a ser procurado na Coluna B.
* @returns {GoogleAppsScript.Spreadsheet.Range | null} O objeto Range da célula do evento ou null se não for encontrado.
*/
function findEventRow(sheet, eventName) {
// Assume que a primeira linha é o cabeçalho, começa a busca da linha 2
const lastRow = sheet.getLastRow();
// Obtém todos os valores da Coluna B (Evento) do cabeçalho até a última linha
const eventColumnValues = sheet.getRange(1, COL_EVENTO_UI, lastRow, 1).getValues();
for (let i = 0; i < eventColumnValues.length; i++) {
// Compara o valor da célula (primeiro elemento do array interno) com o nome do evento
if (eventColumnValues[i][0] === eventName) {
// Retorna o Range da célula do evento (índice i + 1 porque getValues() é baseado em 0 e Sheets em 1)
return sheet.getRange(i + 1, COL_EVENTO_UI);
}
}
return null; // Retorna null se o evento não for encontrado
}
/**
* Função auxiliar para verificar a situação do evento "Fechou RDM" e o estado da RDM.
* Útil para depuração ou verificações pontuais pelo usuário.
*/
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(); // Coluna C (Situação)
const estadoRDM = rdmSheet.getRange(CELULA_RDM_ESTADO).getValue(); // Célula T1
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);
}
/**
* Função para resetar a situação de todos os eventos para "EVENTO PLANEJADO"
* e o estado da RDM para "RDM Fechada". Útil para testes ou para reiniciar a jornada.
*/
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); // Adicionado para resetar RDM A2, A4, D4:H4
const gpsSheet = ss.getSheetByName(NOME_ABA_GPS); // Adicionado para resetar GPS C6
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++) { // Começa da linha 2 (ignora cabeçalho)
interfaceUsuarioSheet.getRange(i, COL_SITUACAO_UI).setValue(EVENTO_PLANEJADO); // Coluna C (Situação)
interfaceUsuarioSheet.getRange(i, COL_ESTADO_ATUAL_UI).clearContent(); // Limpa D
interfaceUsuarioSheet.getRange(i, COL_PROXIMO_ESTADO_UI).clearContent(); // Limpa E
}
if (rdmSheet) {
rdmSheet.getRange(CELULA_RDM_ESTADO).setValue("RDM Fechada"); // T1
rdmSheet.getRange(CELULA_RDM_DATA_ATUAL).clearContent(); // A2
rdmSheet.getRange(CELULA_RDM_HORA_INICIO_JORNADA).clearContent(); // A4
rdmSheet.getRange("D4:H4").clearContent(); // D4 a H4
}
if (gpsSheet) {
gpsSheet.getRange(CELULA_GPS_DATA_HORA_PLANEJADO).clearContent(); // C6
// Opcional: Limpar Coluna R(Plano do Dia) na GPS se desejar resetar as tarefas planejadas
// gpsSheet.getRange(2, COL_GPS_PLANO_DO_DIA, gpsSheet.getLastRow() -1, 1).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.
- Clique no botão "Executar" (ícone de play) na barra de ferramentas do editor de script (você pode selecionar
- 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".
- 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
- 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"?
Nenhum comentário:
Postar um comentário