Módulo: Programação Orçamentária

Sistema completo de gestão da programação orçamentária com funcionalidades de visualização, edição, solicitações e detalhamento

📊 Módulo: Programação Orçamentária

Sistema completo de gestão da programação orçamentária com funcionalidades de visualização, edição, solicitações e detalhamento

📋 Visão Geral do Módulo

ℹ️ Sobre este Módulo

  • Função Principal: Gerenciar programação orçamentária completa
  • Telas: 8 telas
  • Funcionalidades: CRUD completo, aprovações, empenhos, histórico
  • Integrações: SharePoint, Office 365, Planner

🗂️ Telas do Módulo

📊 Programação_Controle

Tela principal de controle e visualização

➕ Programação_Novo

Criação de nova programação

➕ Programação_Editar_2

Visualização da programação

📝 Programacao_Solicitacoes

Gestão de solicitações

🔍 Detalhamento

Detalhes e empenhos


📊 Tela: Programação_Controle

Tela Principal - Controle de Programação

Tipo: Tela de Controle e Gestão

Acesso: APMD e Gestores

📊 Estatísticas da Tela

100+
Controles Totais
4
Módulos/Seções
3
Galleries Principais
12+
Filtros de Busca

⚙️ Evento OnVisible

// Inicializa sistema de navegação por abas
Set(varCurrentNav7, First(colNavMenu7));

// Reseta filtros de pesquisa
UpdateContext({
    searchIDValor: "",
    searchEIValor: "",
    searchFonteValor: "",
    searchGrupoValor: "",
    searchAcaoValor: "",
    searchClassificacaoValor: "",
    searchAcompanhamentoValor: "",
    searchProcedenciaValor: "",
    searchSiafiEntradaValor: "",
    searchUAValor: "",
    searchObjetoValor: ""
});

📑 Sistema de Abas (TabList_Programacao)

📊 Geral

Items: colNavMenu7

DefaultSelectedItems: varCurrentNav7

Tela: Programação_Controle (atual)

📝 Solicitações

Navega para: Programacao_Solicitacoes

OnSelect:

UpdateContext({varCurrentNav7: Self.Selected});
Navigate(Programacao_Solicitacoes)

Colunas Exibidas

ControleCampoDescrição
Acao_ProgramacaoAçãoAção orçamentária
Button_AcaoAção (clicável)Permite ordenação
Button_Cota_AprovadaCota AprovadaValor da cota aprovada
Button_Elemento_ItemE.I.Elemento de Item
Button_GIFPGIFPGrupo/Item/Fonte/Procedência
Button_ObjetoObjetoDescrição do objeto
Button_ReplanejadoReplanejadoValor replanejado
Button_Valor_LiquidadoLiquidadoValor liquidado
CotaAprovadaCotaValor (botão)
ElementoItemE.I.Elemento (botão)
GIFPGIFPIdentificador (botão)
Objeto_ProgramacaoObjetoNome/descrição (botão)
ReplanejadoReplan.Valor replanejado (botão)
SaldoSaldoSaldo disponível (botão)
ValorLiquidadoLiquidadoValor liquidado (botão)

📝 btn_Programacao (SVG_2)

Função: Editar programação

OnSelect:

Set(currObjeto, ThisItem);
Navigate(Programação_Editar_2, ScreenTransition.Fade)

🔍 btn_Detalhamento (SVG_3)

Função: Ver detalhes e empenhos

OnSelect:

Set(currObjeto, ThisItem);
Set(varSelecionarTodosEmpenhos, false);
Navigate(Detalhamento, ScreenTransition.Fade)

🔄 btn_Demanda (SVG_4)

Função: Transformar em demanda

OnSelect:

Set(currObjeto, ThisItem);
UpdateContext({visTransformarDemanda: true})

🔍 Sistema de Filtros - searchBar_Programacao_Certo_3

🎯 Filtros Disponíveis

Sistema de busca avançada com múltiplos critérios simultâneos

VariávelTipoCampo FiltradoComponente
searchIDValorTextID do registroTextInput
searchEIValorTextElemento de ItemComboBox
searchFonteValorTextFonte de RecursoComboBox
searchGrupoValorTextGrupo de DespesaComboBox
searchAcaoValorTextAção OrçamentáriaComboBox
searchClassificacaoValorTextClassificaçãoComboBox
searchAcompanhamentoValorTextTipo de AcompanhamentoComboBox
searchProcedenciaValorTextProcedência do RecursoComboBox
searchSiafiEntradaValorTextSIAFI EntradaTextInput
searchUAValorTextUnidade AdministrativaComboBox
searchObjetoValorTextNome do ObjetoTextInput

💡 Padrão de Nomenclatura

Cada filtro possui duas variáveis associadas:

  • search[Campo]Valor → Valor digitado/selecionado pelo usuário
  • search[Campo]Selecionado → Registro completo do item selecionado

Este padrão garante consistência e facilita manutenção futura.

💼 Container: Empenhos Pendentes

📦 Visibilidade

Variável: visEmpenhosPendentes

Ativação: Button_Empenhos.OnSelect

UpdateContext({visEmpenhosPendentes: !visEmpenhosPendentes})

Campos Exibidos:

  • Acao_Empenhos: Ação orçamentária do empenho
  • EI_Empenhos: Elemento de Item
  • Empenhos_: Número do empenho
  • Entrada_Empenho: SIAFI Entrada
  • GIFP_Empenhos: Identificador GIFP
  • Saida_Empenho: SIAFI Saída
  • UE_Empenhos: Unidade Executora

Ação Principal:

// Button_galEmpenhosPendentes.OnSelect
Set(currObjeto, ThisItem);
Navigate(Detalhamento, ScreenTransition.Fade)

Botões de Controle:

  • ButtonCanvas37: Atualizar base de dados
  • Button_AtualizarBase: Forçar sincronização
// ButtonCanvas37.OnSelect
Refresh(BaseEmpenhos2025);
Notify("Base de empenhos atualizada!", NotificationType.Success)

📝 Container: Solicitações Pendentes (Empenhos_1)

📦 Visibilidade

Variável: visSolicitacoes

Ativação: Button_Solicitacoes.OnSelect

Campos Exibidos:

  • TextCanvas_ObjetoSolicitacoes: Nome do objeto
  • TextCanvas_Solicitacao: Tipo de solicitação
  • TextCanvas25_21 a 25_25: Informações adicionais

Ação Principal:

// Button_galSolicitacoesPendentes.OnSelect
Set(currObjetoSolicitacao, ThisItem);
Navigate(Programação_Editar_1, ScreenTransition.Fade)

🔄 Container: Transformar em Demanda (Transformar_DemandaOrcamentaria)

📦 Visibilidade

Variável: visTransformarDemanda

Ativação: btn_Demanda (na gallery)

Componentes do Modal

📊 Objeto_

Type: Button

Text:

currObjeto.Objeto
📝 TextInput_OrigemdoRecurso

Type: TextInputCanvas

Value:

currObjeto.OrigemRecurso
📅 TextInput_PrevisaoExecucao

Type: TextInputCanvas

Value:

Text(currObjeto.PrevisaoExecucao, "mm/yyyy")
✅ Button_TransformarDemanda

Type: ButtonCanvas

OnSelect:

Patch(
    BaseDemandasOrcamentarias2025,
    Defaults(BaseDemandasOrcamentarias2025),
    {
        Título: currObjeto.Objeto,
        Ação: currObjeto.Ação,
        'U.A': currObjeto.'U.A',
        'E.I.': currObjeto.'E.I.',
        Fonte: currObjeto.Fonte,
        Grupo: currObjeto.Grupo,
        Procedência: currObjeto.Procedência,
        'Origem do recurso': TextInput_OrigemdoRecurso.Text,
        'Previsão de execução do recurso': TextInput_PrevisaoExecucao.Text,
        Status: "Ativo"
    }
);
UpdateContext({visTransformarDemanda: false});
Notify("Demanda criada com sucesso!", NotificationType.Success)
❌ Button_CancelarDemanda

Type: ButtonCanvas

OnSelect:

UpdateContext({visTransformarDemanda: false})

📜 Container: Histórico de Alterações (Alterações)

📦 Visibilidade

Variável: visAlteracoes

Ativação: Button_Alteracoes.OnSelect

Campos do Histórico:

  • Text_Acao_Alteracoes: Ação orçamentária
  • Text_ID_Alteracoes: ID da programação
  • Text_Objeto_Alteracoes: Objeto alterado
  • Text_U.A_Alteracoes: Unidade Administrativa

Botões:

// ButtonCanvas37_3.OnSelect - Aplicar filtros
Navigate(Programação_Controle, ScreenTransition.None);

// ButtonCanvas37_4.OnSelect - Exportar histórico
// (funcionalidade de exportação)

// Rectangle9_1.OnSelect - Fechar painel
UpdateContext({visAlteracoes: false})

📊 Totalizadores (Container5_13)

💰 Cota Aprovada Total

Controle: TextCanvas_Cota_Aprovada

Text(
    Sum(
        Filter(
            PlanejamentoGeral2025,
            // filtros aplicados
        ),
        'Cota Aprovada'
    ),
    "R$ #,##0.00"
)
📈 Total Planejado

Controle: TextCanvas_Total_Planejado

Text(
    Sum(
        Filter(
            PlanejamentoGeral2025,
            // filtros aplicados
        ),
        Replanejado
    ),
    "R$ #,##0.00"
)

➕ Tela: Programação_Novo

Nova Programação - Formulário de Criação

Tipo: Formulário

Modo: New

📊 Estatísticas da Tela

50+
Controles Totais
18
DataCards
1
Formulário

📝 Form6 - Formulário Principal

⚙️ Configurações do Form

DataSource: PlanejamentoGeral2025

Item: Defaults(PlanejamentoGeral2025)

Mode: FormMode.New

DataCards Principais

DataCardCampoTipo de ControleObrigatório
Ação_DataCard2AçãoComboboxCanvas3✅ Sim
Acompanhamento_DataCard1AcompanhamentoDropdownCanvas11✅ Sim
Classificação_DataCard2ClassificaçãoDropdownCanvas12✅ Sim
U.A_DataCard2U.ADropdownCanvas1✅ Sim
E.I._DataCard1E.I.DataCardValue72 (Number)✅ Sim
F_DataCard2FDataCardValue74 (Number)✅ Sim
G_DataCard1GDataCardValue75 (Number)✅ Sim
I_DataCard1IDataCardValue76 (Number)✅ Sim
P_DataCard2PDataCardValue77 (Number)✅ Sim
U.E_DataCard2U.EDataCardValue80 (Number)✅ Sim
U.O_DataCard2U.ODataCardValue81 (Number)✅ Sim
Objeto_DataCard1ObjetoDataCardValue5 (Text)✅ Sim
Processo SEI_DataCard1Processo SEIDataCardValue78 (Text)❌ Não
SIAFI entrada_DataCard1SIAFI entradaDataCardValue66 (Text)✅ Sim
SIAFI saida_DataCard1SIAFI saidaDataCardValue79 (Text)❌ Não
Observações_DataCard1ObservaçõesDataCardValue29 (Text)❌ Não

🎬 Ação de Salvamento

// ButtonCanvas16.OnSelect
If(
    Form6.Valid,
    // Mostra loading
    UpdateContext({visLoading: true});
    
    // Salva o formulário
    SubmitForm(Form6);
    
    // Aguarda conclusão
    If(
        Form6.Error = Blank(),
        // Sucesso
        UpdateContext({visLoading: false});
        Notify("Programação criada com sucesso!", NotificationType.Success);
        Back(),
        // Erro
        UpdateContext({visLoading: false});
        Notify("Erro ao salvar: " & Form6.Error, NotificationType.Error)
    ),
    // Formulário inválido
    Notify("Preencha todos os campos obrigatórios", NotificationType.Warning)
)

🔙 Navegação

// EmailPrevScreen_13.OnSelect
ResetForm(Form6);
Back()

✏️ Tela: Programação_Editar_2

Editar Programação - Modo Detalhamento Completo

Tipo: Edição Completa com DDOs e Observações

Objeto Atual: currObjeto

📊 Estatísticas da Tela

180+
Controles Totais
5
Containers
4
Galleries
36
Campos Mensais

⚙️ Evento OnVisible

// Inicializa componentes
Set(varReset, false);
Set(mudanca, false);
Set(varChecks, false);

// Carrega tarefas relacionadas
Set(varTarefasAPMD, 
    CountRows(
        Filter(
            Planejamento2025Tarefas,
            'ID Programação' = currObjeto.ID
        )
    ) > 0
);

Set(varTarefasArea,
    CountRows(
        Filter(
            BaseSolicitacoesPlanejamento,
            'ID Programação' = currObjeto.ID,
            Status = "Pendente"
        )
    ) > 0
)

📊 Container5_6 - Informações Gerais

📋 Labels de Informação

  • Label_Acao: currObjeto.Ação
  • Label_ElementoItem: currObjeto.'E.I.'
  • Label_GFP: currObjeto.Grupo & "/" & currObjeto.Fonte & "/" & currObjeto.Procedência
  • Label_UA: currObjeto.'U.A'
  • Label_SIAFI_Entrada: currObjeto.'SIAFI entrada'

Campos Financeiros Principais

💰 Label_cota_aprovada

Text:

Text(currObjeto.'Cota Aprovada', "[$-pt-BR]R$ #,##0.00")
💳 Label_credito_autorizado

Text:

Text(currObjeto.'Crédito Autorizado', "[$-pt-BR]R$ #,##0.00")
📊 Label_limite

Text:

Text(currObjeto.Limite, "[$-pt-BR]R$ #,##0.00")
📈 Label_replanejado

Text:

Text(currObjeto.Replanejado, "[$-pt-BR]R$ #,##0.00")
💵 Saldo_Liquidar

Text:

Text(
    currObjeto.Replanejado - currObjeto.'Valor Liquidado',
    "[$-pt-BR]R$ #,##0.00"
)

📅 Planejamento Mensal Detalhado

📊 galPlanejado1_3 - Gallery de Meses

Template: 594498b4-f41f-4bfb-ac9d-7edae7f87336

Items: Collection com 12 registros (um por mês)

Estrutura da Collection:

[
    {Mês: "Janeiro", Planejado: pJan_1, Replanejado: rJan_5, 
     Liquidado: lJan_2, Empenhado: eJan_2},
    {Mês: "Fevereiro", Planejado: pFev_7, Replanejado: rFev_5, 
     Liquidado: lFev_2, Empenhado: eFev_2},
    // ... demais meses
]

Campos Editáveis (sufixo _5):

  • rJan_5, rFev_5, rMar_5, rAbr_5, rMai_5, rJun_5
  • rJul_5, rAgo_5, rSet_5, rOut_5, rNov_5, rDez_5

OnChange de cada campo:

// rJan_5.OnChange (exemplo)
Set(mudanca, true)

🎯 Container_Observacoes - Sistema de Observações

📝 Componente: _observacoes_1

Type: Component (ReutilizÃ

¡vel)

Função: Adicionar e visualizar observações

Componentes da Gallery:

// Label94_14 - Data/Hora
Text(ThisItem.Created, "dd/mm/yyyy hh:mm")

// Label94_15 - Autor
ThisItem.Author.DisplayName

// Label98_7 - Texto da observação
ThisItem.Observação

// Button_Excluir_Obs - Excluir
OnSelect:
    Set(currObservacao, ThisItem);
    UpdateContext({visExcluirObservacao: true})

// Image10_7 - Foto do autor
UsuáriosdoOffice365.UserPhotoV2(ThisItem.Author.Email)

Adicionar Nova Observação:

// Button_Enviar.OnSelect
If(
    !IsBlank(TextInput_Mensagem.Text),
    
    // Adiciona observação
    Patch(
        BaseObservacoesPlanejamento,
        Defaults(BaseObservacoesPlanejamento),
        {
            'ID Programação': currObjeto.ID,
            Observação: TextInput_Mensagem.Text,
            Author: {
                '@odata.type': "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
                Claims: "i:0#.f|membership|" & UsuáriosdoOffice365.MyProfileV2().mail,
                Department: "",
                DisplayName: UsuáriosdoOffice365.MyProfileV2().displayName,
                Email: UsuáriosdoOffice365.MyProfileV2().mail,
                JobTitle: "",
                Picture: ""
            }
        }
    );
    
    // Limpa campo
    Reset(TextInput_Mensagem);
    
    Notify("Observação adicionada!", NotificationType.Success),
    
    Notify("Digite uma observação", NotificationType.Warning)
)

Excluir Observação (Modal):

// Component: _excluirObservacao_1
Visible: visExcluirObservacao

// Button_Excluir_Obs.OnSelect (dentro do modal)
Remove(
    BaseObservacoesPlanejamento,
    currObservacao
);

UpdateContext({visExcluirObservacao: false});
Notify("Observação excluída", NotificationType.Information)

📋 Container_Tarefas/Solicitacoes - Sistema de Tarefas

✅ Gerenciamento de Tarefas do Planner

Integração: Microsoft Planner

Visible: varTarefasAPMD || varTarefasArea

Button_Tarefas - Criar Tarefa

// Button_Tarefas.OnSelect
UpdateContext({visLoading: true});

// Cria tarefa no Planner
Set(taskId,
    Planner.CreateTask(
        "ID_DO_PLANO", // ID do plano no Planner
        {
            title: "Revisão: " & currObjeto.Objeto,
            assignments: {
                "ID_USUARIO": {
                    '@odata.type': "#microsoft.graph.plannerAssignment",
                    orderHint: " !"
                }
            },
            dueDateTime: DateAdd(Now(), 7, Days),
            bucketId: "ID_DO_BUCKET"
        }
    ).id
);

// Registra na base local
If(
    !IsBlank(taskId),
    Patch(
        Planejamento2025Tarefas,
        Defaults(Planejamento2025Tarefas),
        {
            'ID Programação': currObjeto.ID,
            'ID Tarefa Planner': taskId,
            Status: "Criada",
            'Data Criação': Now()
        }
    );
    
    Set(varTarefasAPMD, true);
    Notify("Tarefa criada no Planner!", NotificationType.Success),
    
    Notify("Erro ao criar tarefa", NotificationType.Error)
);

UpdateContext({visLoading: false})

Visible:

Button_Tarefas.Visible: !varTarefasAPMD && _varPermissao = "APMD"

Gallery13_5 - Tarefas Relacionadas

Componentes:

// CheckboxCanvas7_5 - Marcar como concluída
OnCheck:
    // Atualiza no Planner
    Planner.UpdateTask(
        ThisItem.'ID Tarefa Planner',
        "ID_DO_PLANO",
        {
            percentComplete: 100
        }
    );
    
    // Atualiza localmente
    Patch(
        Planejamento2025Tarefas,
        ThisItem,
        {
            Status: "Concluída",
            'Data Conclusão': Now()
        }
    )

// TextCanvas16_5 - Descrição da tarefa
ThisItem.Título & " - " & Text(ThisItem.'Data Criação', "dd/mm/yyyy")

Ação:

// CheckboxCanvas7_4.OnCheck
// Similar ao sistema de tarefas, mas para solicitações

📊 Container6_2 - DDOs Vinculados

📋 Gallery_DDOs

Template: 67998a71-df83-4d17-93cc-07e93f75dce6

Items:

Filter(
    BaseControleDDO_PorObjeto,
    'ID Programação' = currObjeto.ID
)

Campos Exibidos:

ControleCampoDescrição
Label_SEISEINúmero do processo SEI
Label_ValorValorValor do DDO
Label_Valor_FuturoValor FuturoProjeção futura
Label_TotalTotalSoma de valores
TextCanvas7_7ObjetoNome do objeto
TextCanvas7_8StatusStatus do DDO

Ação:

// ButtonCanvas28_5.OnSelect
// Navegar para detalhes do DDO ou abrir documento

🎬 Ações Principais da Tela

💾 Button_Salvar_Detalhamento

OnSelect:

// Similar ao Programação_Editar, mas com mais campos
UpdateContext({visLoading: true});

// Prepara imagem de loading Set(varImagem, First(Shuffle(colImagensLoading)).Imagem);

// Salva alterações Patch( PlanejamentoGeral2025, currObjeto, { // Valores mensais r_Janeiro: Value(rJan_5.Text), r_Fevereiro: Value(rFev_5.Text), r_Março: Value(rMar_5.Text), r_Abril: Value(rAbr_5.Text), r_Maio: Value(rMai_5.Text), r_Junho: Value(rJun_5.Text), r_Julho: Value(rJul_5.Text), r_Agosto: Value(rAgo_5.Text), r_Setembro: Value(rSet_5.Text), r_Outubro: Value(rOut_5.Text), r_Novembro: Value(rNov_5.Text), r_Dezembro: Value(rDez_5.Text),

    // Recalcula total
    Replanejado: Sum([
        Value(rJan_5.Text), Value(rFev_5.Text),
        Value(rMar_5.Text), Value(rAbr_5.Text),
        Value(rMai_5.Text), Value(rJun_5.Text),
        Value(rJul_5.Text), Value(rAgo_5.Text),
        Value(rSet_5.Text), Value(rOut_5.Text),
        Value(rNov_5.Text), Value(rDez_5.Text)
    ])
}

);

// Registra alteração no histórico Patch( BaseNotificacoesPlanejamento, Defaults(BaseNotificacoesPlanejamento), { ‘ID Programação’: currObjeto.ID, Descrição: “Planejamento atualizado por " & UsuáriosdoOffice365.MyProfileV2().displayName, Tipo: “Edição”, Author: { ‘@odata.type’: “#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser”, Claims: “i:0#.f|membership|” & UsuáriosdoOffice365.MyProfileV2().mail, DisplayName: UsuáriosdoOffice365.MyProfileV2().displayName, Email: UsuáriosdoOffice365.MyProfileV2().mail } } );

Set(mudanca, false); UpdateContext({visLoading: false}); Notify(“Alterações salvas com sucesso!”, NotificationType.Success)

🔄 Button_Reset

OnSelect:

Set(varReset, true);

// Reseta todos os campos mensais (sufixo _5 e _6) Reset(rJan_5); Reset(rFev_5); Reset(rMar_5); Reset(rAbr_5); Reset(rMai_5); Reset(rJun_5); Reset(rJul_5); Reset(rAgo_5); Reset(rSet_5); Reset(rOut_5); Reset(rNov_5); Reset(rDez_5);

Reset(rJan_6); Reset(rFev_6); Reset(rMar_6); Reset(rAbr_6); Reset(rMai_6); Reset(rJun_6); Reset(rJul_6); Reset(rAgo_6); Reset(rSet_6); Reset(rOut_6); Reset(rNov_6); Reset(rDez_6);

Set(mudanca, false); Notify(“Valores restaurados!”, NotificationType.Information)

📊 Button_Alteracoes_Detalhamento

OnSelect:

UpdateContext({visSolicitacoes: !visSolicitacoes})

DisplayMode:

If(
    CountRows(
        Filter(
            BaseSolicitacoesPlanejamento,
            'ID Programação' = currObjeto.ID,
            Status = "Pendente"
        )
    ) > 0,
    DisplayMode.Edit,
    DisplayMode.Disabled
)

🏠 Button_Detalhamento

OnSelect:

Navigate(Programação_Controle, ScreenTransition.Fade)

🎯 SVG_50 - Ação Especial

OnSelect:

// Dependendo do contexto (varOpcaoRemanejamento)
Switch(
    varOpcaoRemanejamento,
    "Programação",
        // Lógica para remanejamento de programação
        Set(currItemRemanejamento, currObjeto);
        Navigate(Remanejamento_Novo_Programação),
    "Demanda",
        // Lógica para remanejamento de demanda
        Set(currItemRemanejamento, currObjeto);
        Navigate(Remanejamento_Novo_Demandas),
    // Default
    Notify("Selecione um tipo de remanejamento", NotificationType.Warning)
)

✅ ButtonCanvas8 - Concluir DDOs Selecionados

OnSelect:

// Atualiza DDOs marcados
ForAll(
    Filter(Gallery13_5, CheckboxCanvas7_5.Value = true),
    Patch(
        BaseControleDDO,
        LookUp(BaseControleDDO, ID = ThisRecord.ID),
        {
            Status: "Concluído",
            'Data Conclusão': Now()
        }
    )
);

Set(varChecks, false); Notify(“DDOs concluídos!”, NotificationType.Success); Refresh(BaseControleDDO)

Visible:

varChecks && CountRows(
Filter(Gallery13_5, CheckboxCanvas7_5.Value = true)
) > 0

📋 ButtonCanvas23_4 - Tarefas/Solicitações

OnSelect:

// Alterna visibilidade do painel
Set(varTarefasAPMD, !varTarefasAPMD);
Set(varTarefasArea, !varTarefasArea)

⏱️ Timers

// Timer2_2 - Feedback visual de salvamento
Duration: 2000
OnTimerEnd:
    UpdateContext({visCarregando: false})

// Timer4_2 - Sincronização periódica
Duration: 5000
Repeat: true
AutoStart: varTeste

OnTimerEnd:
    If(
        varTeste,
        // Atualiza dados
        Refresh(BaseObservacoesPlanejamento);
        Refresh(BaseControleDDO);
        Refresh(Planejamento2025Tarefas);
        
        Set(varCarregandoErro, false);
        Set(varTeste, false)
    )

📝 Tela: Programacao_Solicitacoes

Gestão de Solicitações de Programação

Tipo: Listagem e Aprovação

Acesso: Via TabList de Programação_Controle

📊 Estatísticas da Tela

80+
Controles Totais
3
Seções Principais
2
Galleries

⚙️ Evento OnVisible

// Inicializa navegação
Set(varCurrentNav7, 
    LookUp(colNavMenu7, Label = "Solicitações")
)

📑 TabList1_19 - Sistema de Abas

📊 Geral

Navega para: Programação_Controle

📝 Solicitações

Tela Atual

Colunas Exibidas:

ControleCampoTipo
Acao_SolicitacoesAçãoButton
Button_Elemento_Item_SolicitacoesE.I.Button
ElementoItem_SolicitacoesE.I.Button
GIFP_SolicitacoesGIFPButton
Objeto_SolicitacoesObjetoButton
Valor_SolicitacoesValorButton
Text_Acao_SolicitacoesAçãoTextCanvas
Text_GIFP_SolicitacoesGIFPTextCanvas
Text_Objeto_SolicitacoesObjetoTextCanvas
Text_Valor_SolicitacoesValorTextCanvas

Ações nos Itens:

📝 btn_Programacao_Solicitacoes (SVG_36)

OnSelect:

Set(currObjetoSolicitacao, ThisItem);
Navigate(Programação_Editar_1, ScreenTransition.Fade)

🔍 btn_Detalhamento_Solicitacoes (SVG_37)

OnSelect:

Set(currObjeto, ThisItem);
Set(varSelecionarTodosEmpenhos, false);
Navigate(Detalhamento, ScreenTransition.Fade)

💼 Container: Empenhos_7 - Empenhos de Solicitações

📦 Visibilidade

Variável: visEmpenhosPendentes

Ativação: Button_Empenhos_Solicitacoes.OnSelect

galEmpenhosPendentes_4

Ação:

// ButtonCanvas37_13.OnSelect
Set(currObjeto, ThisItem);
Navigate(Detalhamento, ScreenTransition.Fade)

Botões de Controle:

// ButtonCanvas37_11 - Atualizar
Refresh(BaseEmpenhos2025);
Notify("Base atualizada!", NotificationType.Success)

// ButtonCanvas37_12 - Exportar
UpdateContext({visLoading: true});
Set(varImagem, First(Shuffle(colImagensLoading)).Imagem);
Export(galEmpenhosPendentes_4, "Empenhos_Solicitacoes_" & 
       Text(Now(), "yyyymmdd"));
UpdateContext({visLoading: false})

📜 Container: Alterações_1 - Histórico

📦 Visibilidade

Variável: visAlteracoes

Ativação: Button_Alteracoes_Solicitacoes.OnSelect

Gallery1_5

Ações:

// ButtonCanvas37_8.OnSelect - Aplicar Filtros
// (lógica de filtros)

// ButtonCanvas37_6.OnSelect - Exportar Histórico
// (lógica de exportação)

// Rectangle9_9.OnSelect - Fechar
UpdateContext({visAlteracoes: false})

📊 Totalizadores

💰 TextCanvas19_7

Text:

Text(
    Sum(
        Filter(Gallery_Programacao_Solicitacoes, ...),
        'Cota Aprovada'
    ),
    "R$ #,##0.00"
)
📈 TextCanvas19_8

Text:

Text(
    Sum(
        Filter(Gallery_Programacao_Solicitacoes, ...),
        Replanejado
    ),
    "R$ #,##0.00"
)

🔍 Tela: Detalhamento

Detalhamento e Empenhos

Tipo: Visualização Detalhada + Gestão de Empenhos

Objeto Atual: currObjeto

📊 Estatísticas da Tela

70+
Controles Totais
22
Campos de Detalhes
1
Gallery de Empenhos

📋 Container_Detalhamento - Campos Principais

🎯 DropdownAcao

Type: DropdownCanvas

Items: Distinct(BaseProgramasAcoes, Ação)

Default: currObjeto.Ação

📊 Dropdown_Acompanhamento

Type: DropdownCanvas

Items: AcompanhamentoClassificacao.Acompanhamento

Default: currObjeto.Acompanhamento

📋 Dropdown_Classificacao

Type: DropdownCanvas

Items: AcompanhamentoClassificacao.Classificação

Default: currObjeto.Classificação

🏢 Dropdown_UA

Type: DropdownCanvas

Items: Distinct(BaseOrdenadores, 'U.A')

Default: currObjeto.'U.A'

Campos Numéricos

ControleCampoDefault
TextInput_E.IE.I.currObjeto.'E.I.'
TextInput_EmpenhoEmpenhocurrObjeto.Empenho
TextInput_FFcurrObjeto.F
TextInput_GGcurrObjeto.G
TextInput_IIcurrObjeto.I
TextInput_PPcurrObjeto.P
TextInput_U.EU.EcurrObjeto.'U.E'
TextInput_U.OU.OcurrObjeto.'U.O'
TextInput_Cota_AprovadaCota AprovadacurrObjeto.'Cota Aprovada'
TextInput_CreditoCrédito AutorizadocurrObjeto.'Crédito Autorizado'
TextInput_LimiteLimitecurrObjeto.Limite
TextInput_Valor_LOAValor LOAcurrObjeto.'Valor LOA'

Campos de Texto

ControleCampoDefault
TextInput_ObjetoObjetocurrObjeto.Objeto
TextInput_ProgramadeTrabalhoPrograma de TrabalhocurrObjeto.'Programa de Trabalho'
TextInput_SEI_InstrucaoSEI InstruçãocurrObjeto.'SEI Instrução'
TextInput_SEI_ExecucaoSEI ExecuçãocurrObjeto.'SEI Execução'
TextInput_Setor_ReferenciaSetor de ReferênciacurrObjeto.'Setor de Referência'
TextInput_Siafi_EntradaSIAFI EntradacurrObjeto.'SIAFI entrada'
TextInput_SIAFI_SaidaSIAFI SaídacurrObjeto.'SIAFI saida'

💼 Container1 - Gestão de Empenhos

📦 Visibilidade

Variável: visEmpenhos

Ativação: ButtonEmpenhos.OnSelect

Componentes:

// Checkbox1_2 - Seleção do empenho
Default: varSelecionarTodosEmpenhos

OnCheck:
    ClearCollect(
        colEmpenhos,
        If(
            IsEmpty(colEmpenhos),
            Table(ThisItem),
            Collect(colEmpenhos, ThisItem)
        )
    )

OnUncheck:
    Remove(
        colEmpenhos,
        LookUp(colEmpenhos, ID = ThisItem.ID)
    )

DisplayMode:
    If(
        !IsBlank(ThisItem.'Número Empenho'),
        DisplayMode.Edit,
        DisplayMode.Disabled
    )

// TextCanvas10_3 - Informações do empenho
ThisItem.'Número Empenho' & " - R$ " & 
Text(ThisItem.'Valor Empenhado', "#,##0.00")

Botões de Controle:

☑️ ButtonCanvas38 - Selecionar Todos

OnSelect:

Set(varSelecionarTodosEmpenhos, 
    !varSelecionarTodosEmpenhos
);

🔗 ButtonCanvas26_8 - Vincular Empenhos

OnSelect:

// Vincula empenhos selecionados à programação
ForAll(
    colEmpenhos,
    Patch(
        BaseEmpenhos2025,
        LookUp(BaseEmpenhos2025, ID = ThisRecord.ID),
        {
            'ID Programação': currObjeto.ID,
            Status: "Vinculado"
        }
    )
);

Clear(colEmpenhos); Set(varSelecionarTodosEmpenhos, false); Notify(“Empenhos vinculados!”, NotificationType.Success); Refresh(BaseEmpenhos2025)

🔓 ButtonCanvas26_9 - Desvincular Empenhos

OnSelect:

// Mostra loading
UpdateContext({visLoading: true});
Set(varImagem, First(Shuffle(colImagensLoading)).Imagem);

// Desvincula empenhos selecionados ForAll( Filter(galEmpenhos_3, Checkbox1_2.Value = true), Patch( BaseEmpenhos2025, ThisRecord, { ‘ID Programação’: Blank(), Status: “Disponível” } ) );

// Registra no histórico Collect( colEmpenhos, Filter(galEmpenhos_3, Checkbox1_2.Value = true) );

Clear(colEmpenhos); Set(varSelecionarTodosEmpenhos, false); UpdateContext({visLoading: false}); Notify(“Empenhos desvinculados!”, NotificationType.Information); Refresh(BaseEmpenhos2025)

🎬 Ações Principais da Tela

💾 Button_Salvar

OnSelect:

// Valida campos obrigatórios
If(
    !IsBlank(TextInput_Objeto.Text) &&
    !IsBlank(Dropdown_UA.Selected.Result),
// Salva alterações
Patch(
    PlanejamentoGeral2025,
    currObjeto,
    {
        Ação: DropdownAcao.Selected.Result,
        Acompanhamento: Dropdown_Acompanhamento.Selected.Result,
        Classificação: Dropdown_Classificacao.Selected.Result,
        'U.A': Dropdown_UA.Selected.Result,
        'E.I.': Value(TextInput_E.I.Text),
        Empenho: TextInput_Empenho.Text,
        F: Value(TextInput_F.Text),
        G: Value(TextInput_G.Text),
        I: Value(TextInput_I.Text),
        P: Value(TextInput_P.Text),
        'U.E': Value(TextInput_U.E.Text),
        'U.O': Value(TextInput_U.O.Text),
        Objeto: TextInput_Objeto.Text,
        'Programa de Trabalho': TextInput_ProgramadeTrabalho.Text,
        'SEI Instrução': TextInput_SEI_Instrucao.Text,
        'SEI Execução': TextInput_SEI_Execucao.Text,
        'Setor de Referência': TextInput_Setor_Referencia.Text,
        'SIAFI entrada': TextInput_Siafi_Entrada.Text,
        'SIAFI saida': TextInput_SIAFI_Saida.Text,
        'Cota Aprovada': Value(TextInput_Cota_Aprovada.Text),
        'Crédito Autorizado': Value(TextInput_Credito.Text),
        Limite: Value(TextInput_Limite.Text),
        'Valor LOA': Value(TextInput_Valor_LOA.Text)
    }
);

Notify("Detalhamento salvo!", NotificationType.Success);
Back(),

// Campos obrigatórios faltando
Notify("Preencha todos os campos obrigatórios", NotificationType.Warning)

)

❌ Button_Excluir

OnSelect:

Set(varExcluir, true);
UpdateContext({visExcluirProgramacao: true})

📜 Button_Historico

OnSelect:

Set(currObjeto, currObjeto);
Navigate(Programação_Editar, ScreenTransition.Fade)

📝 ButtonEmpenhos

OnSelect:

UpdateContext({visEmpenhos: !visEmpenhos})

🏠 Button_Programacao

OnSelect:

Navigate(Programação_Controle, ScreenTransition.Fade)

⚠️ Confirmacao_1 - Modal de Exclusão

Ação de Confirmar Exclusão:

// Dentro do componente Confirmacao_1
// Button Confirmar.OnSelect
If(
    varExcluir,
    
    // Remove programação
    Remove(
        PlanejamentoGeral2025,
        currObjeto
    );
    
    // Remove dados relacionados
    RemoveIf(
        BaseEmpenhos2025,
        'ID Programação' = currObjeto.ID
    );
    
    RemoveIf(
        BaseControleDDO,
        'ID Programação' = currObjeto.ID
    );
    
    RemoveIf(
        BaseObservacoesPlanejamento,
        'ID Programação' = currObjeto.ID
    );
    
    Set(varExcluir, false);
    UpdateContext({visExcluirProgramacao: false});
    Notify("Programação excluída!", NotificationType.Warning);
    Navigate(Programação_Controle, ScreenTransition.Fade)
)

🧪 Tela: Screen3

Tela de Testes e Desenvolvimento

Tipo: Ambiente de Testes

Uso: Desenvolvimento e debug

📊 Estatísticas da Tela

40+
Controles de Teste
10+
ComboBox de Filtros

⚠️ Atenção - Tela de Desenvolvimento

Esta tela é utilizada para:

  • Testar novos componentes antes de implementar
  • Validar fórmulas complexas
  • Debug de problemas
  • Prototipar novas funcionalidades

Não deve ser acessível em produção!

🛠️ Componentes Principais

// navBar_1 - Barra de navegação de teste
// ButtonCanvas18 - Botão de ação 1
// ButtonCanvas32 - Botão de ação 2 (carrega imagens)
OnSelect:
    ClearCollect(
        collectionImagens,
        {ID: 1, Imagem: 'teste1'},
        {ID: 2, Imagem: 'teste2'})

// ButtonCanvas36 - Botão de ação 3
// Image9 - Preview de imagem
Image: First(collectionImagens).Imagem

// Diversos ComboBox de filtros (scEI, scFonte, scGrupo, etc.)
// Usados para testar lógica de filtros antes de implementar nas telas principais

📊 Variáveis Globais do Módulo

VariávelTipoEscopoFunção
currObjetoRecordGlobalItem de programação selecionado
currObjetoSolicitacaoRecordGlobalItem de solicitação selecionado
varCurrentNav7RecordGlobalAba ativa do TabList (Geral/Solicitações)
varSelecionarTodosEmpenhosBooleanGlobalSeleção em massa de empenhos
mudancaBooleanGlobalIndica alterações não salvas
varResetBooleanGlobalFlag de reset de formulários
varSalvarBooleanGlobalFlag de salvamento bem-sucedido
varCarregandoErroBooleanGlobalControla spinner de loading
varTesteBooleanGlobalControla timer de sincronização
varChecksBooleanGlobalSeleção em massa de DDOs
varTarefasAPMDBooleanGlobalIndica existência de tarefas APMD
varTarefasAreaBooleanGlobalIndica existência de solicitações da área
varExcluirBooleanGlobalFlag para confirmação de exclusão
varImagemTextGlobalImagem de loading selecionada
taskIdTextGlobalID da tarefa criada no Planner
varOpcaoRemanejamentoTextGlobalTipo de remanejamento (Programação/Demanda)

🧭 Variáveis de Contexto (por tela)

VariávelTipoTelaFunção
visEmpenhosPendentesBooleanProgramação_ControleMostra/oculta empenhos
visSolicitacoesBooleanProgramação_Controle, Editar_2Mostra/oculta solicitações
visTransformarDemandaBooleanProgramação_ControleMostra/oculta modal de transformação
visAlteracoesBooleanProgramação_Controle, SolicitacoesMostra/oculta histórico
visObservacoesBooleanProgramação_EditarMostra/oculta observações
visMovimentacoesBooleanProgramação_EditarMostra/oculta movimentações
visDetalharBooleanProgramação_EditarMostra/oculta campos detalhados
visDetalhar2BooleanProgramação_Editar_1Mostra/oculta campos detalhados
visEmpenhosBooleanDetalhamentoMostra/oculta gallery de empenhos
visExcluirProgramacaoBooleanDetalhamentoMostra/oculta modal de exclusão
visExcluirObservacaoBooleanProgramação_Editar_2Mostra/oculta modal de exclusão de observação
visLoadingBooleanTodasMostra/oculta tela de loading
visCarregandoBooleanProgramação_EditarMostra/oculta spinner inline
currObservacaoRecordProgramação_Editar_2Observação a ser excluída

🔍 Padrão de Filtros

Todas as variáveis de filtro seguem o mesmo padrão em todas as telas do módulo:

  • search[Campo]Valor - Valor digitado/selecionado
  • search[Campo]Selecionado - Registro completo

📊 Collections do Módulo

CollectionCriada emFunçãocolNavMenu7OnStart (App)Navegação entre Geral e SolicitaçõescolEmpenhosDetalhamentoArmazena empenhos selecionados temporariamentecolImagensLoadingOnStart (App)Imagens para telas de loadingcollectionImagensScreen3Testes de imagens

📚 Fontes de Dados Utilizadas

Fonte de DadosTipoFunção no Módulo
PlanejamentoGeral2025SharePoint ListDados principais da programação
BaseEmpenhos2025SharePoint ListEmpenhos vinculados
BaseSolicitacoesPlanejamentoSharePoint ListSolicitações de alteração
BaseNotificacoesPlanejamentoSharePoint ListHistórico de alterações
BaseObservacoesPlanejamentoSharePoint ListObservações dos usuários
BaseControleDDOSharePoint ListDDOs vinculados à programação
BaseControleDDO_PorObjetoSharePoint ListVista de DDOs por objeto
Planejamento2025TarefasSharePoint ListTarefas do Planner vinculadas
BaseOrdenadoresSharePoint ListLista de ordenadores e UAs
BaseProgramasAcoesSharePoint ListAções orçamentárias disponíveis
AcompanhamentoClassificacaoSharePoint ListTipos de acompanhamento e classificação
ElementosItemSharePoint ListElementos de Item disponíveis
PermissoesSistemaAPMDSharePoint ListControle de permissões
UsuáriosdoOffice365Office 365 ConnectorInformações do usuário logado
PlannerMicrosoft PlannerCriação e gestão de tarefas

🔗 Fluxo de Navegação do Módulo

graph TD
    A[Capa_Nova] --> B[Programação_Controle]
    
    B --> C[Programação_Novo]
    B --> D[Programação_Editar_2]
    B --> E[Detalhamento]
    B --> F[Programacao_Solicitacoes]
    
    C --> B
    
    D --> G[Programação_Editar]
    D --> E
    
    E --> D
    E --> B
    
    F --> H[Programação_Editar_1]
    F --> E
    F --> B
    
    H --> F
    
    B -.TabList.-> F
    F -.TabList.-> B
    
    I[Screen3] -.Testes.-> B
    
    style A fill:#667eea
    style B fill:#28a745
    style C fill:#17a2b8
    style D fill:#ffc107
    style E fill:#dc3545
    style F fill:#6f42c1
    style G fill:#fd7e14
    style H fill:#20c997
    style I fill:#6c757d

💡 Dicas de Uso do Módulo

📊 Hierarquia de Edição

Existem 3 níveis de edição:

  • Programação_Editar: Visualização + planejamento mensal
  • Programação_Editar_1: Aprovação de solicitações
  • Programação_Editar_2: Edição completa + DDOs + Observações

🔄 Sincronização de Dados

Os timers automáticos (Timer4) atualizam dados a cada 5 segundos quando ativos. Isso garante que múltiplos usuários vejam as mesmas informações.

💾 Salvamento Inteligente

A variável mudanca controla quando o botão salvar está ativo. Só é possível salvar quando há alterações detectadas.

🖼️ Experiência de Loading

As imagens de loading são escolhidas aleatoriamente da colImagensLoading para tornar a espera mais agradável.

📝 Observações e Histórico

Todas as alterações são registradas automaticamente em BaseNotificacoesPlanejamento com timestamp e autor.

✅ Integração com Planner

Tarefas criadas no app são sincronizadas com Microsoft Planner, permitindo acompanhamento em múltiplas plataformas.

🔗 Vínculos de Empenhos

Empenhos podem ser vinculados e desvinculados livremente na tela de Detalhamento, com histórico completo das mudanças.

🎯 Transformação em Demanda

Ao transformar programação em demanda, todos os dados principais são copiados automaticamente, economizando tempo de digitação.

⚠️ Considerações Importantes

🔐 Permissões Diferenciadas

Algumas funcionalidades (como criar tarefas no Planner) só aparecem para usuários com perfil APMD (_varPermissao = "APMD").

💾 Salvamento Manual

As alterações em valores mensais NÃO são salvas automaticamente. O usuário deve clicar em Salvar explicitamente.

🔄 Navegação com Mudanças

O sistema avisa antes de sair de telas com alterações não salvas (if mudanca = true), evitando perda de dados.

📊 Performance com Filtros

Aplicar múltiplos filtros simultaneamente pode impactar a performance. Use apenas os filtros necessários.

🔗 Dependências de Dados

Excluir uma programação remove automaticamente todos os dados relacionados (empenhos, DDOs, observações). Esta ação é irreversível!

⏱️ Timers e Sincronização

Os timers de sincronização (Timer4) consomem recursos. Eles são automaticamente desativados quando a variável varTeste é false.

📱 Layout Desktop

Este módulo foi projetado para desktop/tablet (1366x768). Não é otimizado para mobile.

🎨 Componentes Reutilizáveis

🔍 searchBar_Programacao_Certo_*

Usado em: Todas as telas do módulo

Função: Sistema de filtros padronizado

Props: Variáveis search* (11 filtros)

🧭 navBar_*

Usado em: Todas as telas

Função: Barra de navegação superior

Recursos: Menu, notificações, perfil, configurações

⏳ loading_*

Usado em: Operações demoradas

Função: Tela de loading com imagem aleatória

Controle: visLoading (boolean)

❌ Confirmacao_1

Usado em: Detalhamento

Função: Modal de confirmação de exclusão

Controle: visExcluirProgramacao

📝 _observacoes_1

Usado em: Programação_Editar_2

Função: Sistema de observações completo

Recursos: Adicionar, listar, excluir

🗑️ _excluirObservacao_1

Usado em: Programação_Editar_2

Função: Modal de confirmação de exclusão de observação

Controle: visExcluirObservacao

📈 Métricas e KPIs

📊 Total Cota Aprovada

Cálculo:

Sum(
    Filter(PlanejamentoGeral2025, [filtros]),
    'Cota Aprovada'
)

Localização: Container5_13 (Programação_Controle)

📈 Total Replanejado

Cálculo:

Sum(
    Filter(PlanejamentoGeral2025, [filtros]),
    Replanejado
)

Atualizado: Automaticamente ao salvar valores mensais

💰 Saldo a Liquidar

Cálculo:

currObjeto.Replanejado - 
currObjeto.'Valor Liquidado'

Localização: Programação_Editar_2

📋 Solicitações Pendentes

Cálculo:

CountRows(
    Filter(
        BaseSolicitacoesPlanejamento,
        Status = "Pendente"
    )
)

Indicador: Badge na aba Solicitações

🔧 Manutenção e Troubleshooting

❓ Problema: Dados não aparecem na gallery

Possíveis Causas:

  • Filtros muito restritivos
  • Permissões no SharePoint
  • Connection offline

Solução:

// Limpar todos os filtros
UpdateContext({
    searchIDValor: "",
    searchEIValor: "",
    // ... demais filtros
});
// Forçar refresh
Refresh(PlanejamentoGeral2025)

❓ Problema: Salvamento não funciona

Verificar:

  • Variável mudanca = true?
  • Campos obrigatórios preenchidos?
  • Permissão de edição na lista SharePoint?

Debug:

// Adicionar label temporário
Label.Text: 
"Mudança: " & Text(mudanca) & 
" | Válido: " & Text(!IsBlank(currObjeto))

❓ Problema: Timer não para

Causa: Variável varTeste permanece true

Solução:

// Forçar parada
Set(varTeste, false);
Set(Timer4.Start, false)

❓ Problema: Integração Planner falha

Verificar:

  • Conexão Planner está ativa?
  • IDs do Plano e Bucket estão corretos?
  • Usuário tem permissão no Planner?

Logs:

// Adicionar tratamento de erro
Set(taskId,
    IfError(
        Planner.CreateTask(...).id,
        Notify(
            "Erro: " & FirstError.Message,
            NotificationType.Error
        );
        Blank()
    )
)

📝 Checklist de Implementação

✅ Antes de Usar o Módulo

  • ☐ Todas as listas SharePoint estão criadas?
  • ☐ Permissões configuradas corretamente?
  • ☐ Conexões (Office 365, Planner) estão ativas?
  • ☐ IDs do Planner (Plano, Bucket) estão configurados?
  • ☐ Collections globais (colNavMenu7, colImagensLoading) foram criadas?
  • ☐ Usuários cadastrados em PermissoesSistemaAPMD?
  • ☐ Imagens de loading foram carregadas como Resources?
  • ☐ Teste de navegação entre todas as telas?
  • ☐ Teste de salvamento em cada tela de edição?
  • ☐ Teste de filtros funcionando corretamente?
Última modificação October 22, 2025: Programacao (081f3df)