Skip to content

TDD — Relatório de EBD (Preencher)

Em elaboração

Este TDD define os cenários de teste e critérios de aceite para a funcionalidade “Preencher relatório de EBD”, com controle por fases e autorização por papel + vínculo + escopo.

O fluxo é dividido em duas ações operacionais distintas:

  1. Criar sessão de EBD (create_ebd_session)

    • responsabilidade da governança da ocorrência (igreja/ministério);
    • cria a sessão e define classes/responsáveis presentes.
  2. Preencher classe da sessão (fill_ebd_class_report)

    • responsabilidade de execução por classe;
    • classes da sessão são visíveis para perfis operacionais;
    • preenchimento efetivo depende de vínculo aprovado por classe.

Regra:

  • sem sessão criada não há preenchimento de classe.
IDCenárioDadoQuandoEntão
V1Ação visível para professorUsuário com EBD_TEACHER aprovado e matriz READ/FULLAcessa aba Ações”Preencher relatório de EBD” aparece na lista
V2Ação visível para secretárioUsuário com EBD_SECRETARY aprovado e matriz READ/FULLAcessa aba Ações”Preencher relatório de EBD” aparece na lista
V3Ação visível para assistente vinculadoUsuário com papel de assistente e matriz READ/FULLAcessa aba Ações”Preencher relatório de EBD” aparece conforme política híbrida
V4Ação oculta por matriz NONEUsuário com minRole elegível, porém matriz NONE para EBD/FILL_REPORTAcessa aba Ações”Preencher relatório de EBD” não aparece
V5Ação oculta sem perfilUsuário não logadoAcessa aba Ações”Preencher relatório de EBD” não aparece
IDCenárioDadoQuandoEntão
N1Navegação para páginaUsuário com perfil autorizadoToca em “Preencher relatório de EBD”Abre EbdReportPage
N2RetornoNa EbdReportPageToca em VoltarRetorna à Home
IDCenárioDadoQuandoEntão
P1Exibição inicialUsuário na EbdReportPagePágina carregaTítulo, descrição, seletor de igreja e data visíveis
P2Botão voltarNa EbdReportPageAppBar com leadingÍcone de voltar funcional
P3Igreja pré-selecionadaPerfil com organizationNode/unitIdPágina carregaDropdown mostra igreja do perfil
P4Data domingoUsuário toca no seletor de dataDatePicker abreApenas domingos selecionáveis
P5ContinuarIgreja e data selecionadosToca em ContinuarCarrega ou cria EbdSession; exibe sessão

Criação de EbdSession e inclusão de classes

Section titled “Criação de EbdSession e inclusão de classes”
IDCenárioDadoQuandoEntão
C1Registrar nova EBDUsuário com perfil (EBD_SECRETARY ou superior)Não existe sessão para unidade+data e toca em “Registrar nova EBD”Cria EbdSession; fluxo de inclusão de classes inicia
C2Catálogo de classes oficialUnidade com classes habilitadas em class_refUsuário abre criação de sessãoSistema lista todas as classes habilitadas da igreja
C3Pré-seleção pela última EBDUnidade com EBD anteriorUsuário cria nova EbdSessionClasses usadas na última EBD aparecem pré-selecionadas
C4Ajuste manual da seleção em loteLista de classes carregadaUsuário marca/desmarca classesSessão mantém somente classes selecionadas
C5Sessão sem EBD anteriorUnidade sem sessão anteriorUsuário cria nova EbdSessionNenhuma classe vem pré-selecionada; todas habilitadas continuam disponíveis
C6Responsáveis da sessãoUsuários elegíveis na igrejaUsuário seleciona responsáveisEbdSession.principals[] recebe múltiplos UIDs elegíveis
C7Classes como subcoleçãoEbdSession criada com classesPersistência no FirestoreLessons em ebds/{sessionId}/lessons/{lessonId}
C8Sem formulário detalhado da classe na criaçãoSessão em criação (create_ebd_session)Usuário seleciona classesSistema não exibe formulário operacional por classe nesse momento
C9Lesson mínima na criaçãoClasse selecionada na criação de sessãoSessão é salvaLesson nasce com dados mínimos da classe e status=CREATED

Ação separada de preenchimento por classe

Section titled “Ação separada de preenchimento por classe”
IDCenárioDadoQuandoEntão
CL1Sessão obrigatóriaNão existe sessão para a data/unidadeUsuário tenta preencher classeOperação negada com orientação para criar sessão
CL2Professor preenche sua classeSessão existente e professor vinculadoEntra no fluxo de classePode editar dados da classe
CL3Assistente preenche sua classeSessão existente e assistente vinculadoEntra no fluxo de classePode editar dados da classe
CL4Classe fora de escopo para ediçãoSessão existente, sem vínculo com a classe selecionadaTenta salvar preenchimentoOperação negada até vínculo aprovado
CL5Combo de classes com visão completa da sessãoSessão existente com várias classesUsuário abre ação de classeCombo lista todas as classes da sessão, independentemente de vínculo
CL6Metadados e responsáveis por classeClasse selecionada no fluxo de classeSistema carrega classeExibe nome, descrição e responsáveis vinculados (professor/assistentes)
CL6bUI — professores e assistentes separadosLesson com teacherIds/assistantIdsUsuário no fluxo Preencher classe da sessãoCombo apenas com professores da lesson + opção ”— Nenhum —”; Assistentes em chips apenas com IDs de assistantIds/monitorId (sem lista unificada)
CL6cSeleção de classe antes do formulárioSessão carregada com várias lessonsCombo Classe vinculada inicia em “Selecione a classe”Dados operacionais (professor/assistentes, formulário da lesson) só aparecem após escolher uma classe
CL6dCalendário da data EBDUsuário toca na dataAbre CalendarDatePicker (domingos)Ao tocar num domingo válido, fecha o diálogo e confirma a data (sem botão OK)
CL6eVínculo bloqueia edição de papéis na lessonUsuário já está em teacherIds/assistantIdsTela de preenchimentoCombos professor/assistente visíveis porém bloqueados (AbsorbPointer) com mensagem explicativa
CL6fStatus não operacionalnotHeldToday ou notExistsUsuário altera status no card da lessonQuantidades (alunos, visitantes, etc.) e editora/revista bloqueados e zerados/limpos
CL7Sugestão de andamento no preenchimentoLesson recém-criada com status=CREATEDProfessor/assistente abre a classe para preencherStatus operacional é sugerido como IN_PROGRESS
CL8Solicitação de adesão à classeUsuário operacional sem vínculo na classe selecionada; tem EBD_TEACHER e/ou EBD_ASSISTENT APPROVED no perfilMarca checkbox(es) conforme papel desejado (pré-seleção pelo activeRole quando aplicável) e envia pedidoUma solicitação = um requestedRole (TEACHER ou ASSISTANT); sem papel aprovado correspondente, UI orienta e botão desabilitado
CL9Aprovação de adesão por professor vinculadoPedido pendente de adesão como assistenteProfessor já vinculado na classe aprovaSolicitante passa a constar em assistantIds / vínculo de assistente
CL10Aprovação de adesão por governança local (mesma igreja)Pedido pendente (professor ou assistente)Usuário com EBD_SUPERINTENDENT ou LOCAL_SECRETARY aprovado no perfil e mesma unitId da sessão/classeSolicitante passa a constar nos vínculos da classe
CL10bAprovação de adesão por admin do ministérioPedido pendente (professor ou assistente)Usuário com MINISTRY_ADMIN ou PLATFORM_ADMIN aprovado no perfil e mesmo ministryId da lessonSolicitante passa a constar nos vínculos da classe
CL11Rejeição de adesãoPedido pendente de adesãoAprovador rejeitaPedido fica rejeitado e não libera preenchimento
CL12Assistente salva sem professor na lessonSessão gravável; assistente vinculado (assistantIds/monitorId); teacherIds/teacherId vazios ou incompletosSalva preenchimento da classePermitido — escopo exige apenas vínculo do ator com a lesson; não exige o outro papel preenchido
CL13Professor salva sem assistentes na lessonSessão gravável; professor vinculado (teacherIds/teacherId); assistentes vaziosSalva preenchimento da classePermitido — idem CL12

Regra explícita — quem aprova vinculação à classe (CLASS_MEMBERSHIP_REQUEST)

Section titled “Regra explícita — quem aprova vinculação à classe (CLASS_MEMBERSHIP_REQUEST)”

Escopo: ministryId da lesson = ministryId do aprovador. A igreja é a unitId da sessão EBD (ou da lesson, quando preenchida).

Papel solicitado na adesãoPode aprovar
ASSISTANT (assistente de classe)(1) Qualquer professor já vinculado à lesson (teacherIds / teacherId); (2) EBD_SUPERINTENDENT ou LOCAL_SECRETARY com assignment APPROVED e mesma unitId da ocorrência; (3) MINISTRY_ADMIN ou PLATFORM_ADMIN com assignment APPROVED (âmbito do ministério).
TEACHER (professor)(1) Não depende de outro professor vinculado; (2) EBD_SUPERINTENDENT ou LOCAL_SECRETARY mesma igreja (unitId); (3) MINISTRY_ADMIN / PLATFORM_ADMIN como acima.

A autorização de aprovação usa role_assignments com status APPROVED, não apenas o active_role exibido na sessão — assim um usuário com superintendência aprovada continua podendo aprovar mesmo que o papel ativo operacional seja outro (ex.: assistente).

Fonte de verdade (runtime atual): CREATED -> IN_PROGRESS -> CONCLUDED -> CLOSED.

Mapeamento legado de nomenclatura:

  • PREENCHIMENTO ~ CREATED/IN_PROGRESS
  • REVISAO ~ IN_PROGRESS
  • CONCLUIDO ~ CONCLUDED
  • ENVIADO/APROVADO ~ CLOSED
IDCenárioDadoQuandoEntão
F1Iniciar preenchimentoSessão em CREATED com dados mínimosUsuário autorizado inicia ediçãoSessão vai para IN_PROGRESS
F2ConcluirSessão em IN_PROGRESS com classes preenchidasUsuário autorizado concluiSessão vai para CONCLUDED
F3Fechar envioSessão em CONCLUDED e usuário com escopo de envioUsuário fecha relatórioSessão vai para CLOSED
F4Bloqueio pós-fechamentoSessão em CLOSEDPapel operacional tenta editarBackend bloqueia edição
F5Reabertura controladaSessão em CLOSEDGovernança autoriza reaberturaSessão volta para IN_PROGRESS
F6Adesão bloqueada em fase finalSessão em CLOSEDUsuário solicita adesão de classeBackend rejeita solicitação
F7Revisão de adesão bloqueada em fase finalSessão em CLOSEDAprovador tenta aprovar/rejeitar adesãoBackend rejeita operação

Dados no perfil (Firestore users/{email}): conferir status, ministry_id, active_role, primary_role, role_assignments (cada item com roleId/role_id e status).

Regra do gateway para a matriz (process-user-action.ts, resolveActorRoleForAccess): ordem active_role → primary_role → primeiro item APPROVED na lista role_assignments → fallback papel no token. A matriz usa esse papel contra resourceId/actionId da ação (ex.: USER_EBD_LESSONS_LIST_BY_SESSION → LESSON / FILL_CLASS_REPORT / READ).

Logs no Cloud Functions (prefixo fixo; correlacionar com meta.request_id do POST):

  • [AccessDebug][<request_id>] resolveActorRole ... — se o ministério da conta bate com o esperado, status da conta, lista de papéis aprovados, origem do papel (activeRole | primaryRole | firstApprovedAssignment | fallback token).
  • [AccessDebug] assertMinistryAccess DENY ... — sem papel resolvido, ou matriz negou com evalCode / evalSource / matchedRole (via resolveAccessLevel).

No app (HTTP ≥ 400): repositórios HTTP de sessão e lesson anexam [FORBIDDEN_ACCESS_LEVEL] (ou outro error.code do JSON) à mensagem, para ver na UI sem inspecionar o Network.

Escopo em USER_EBD_SESSION_UPDATE (gateway): autorização de escrita na sessão para perfil operacional deve considerar se o account.id está vinculado como professor ou assistente em qualquer lesson da subcoleção ebds/{sessionId}/lessons — não apenas uma amostra arbitrária de um documento. Implementação em process-user-action.ts (handleEbdSessionUpdate): percorre todas as lessons da sessão antes de decidir FORBIDDEN_CLASS_SCOPE.

Ordem de persistência no app (preenchimento por classe): no fluxo fill_ebd_class_report, gravar primeiro a lesson alvo (USER_EBD_LESSON_*) e em seguida a sessão (USER_EBD_SESSION_UPDATE), para que totais/agregados da sessão não bloqueiem o salvamento dos dados operacionais da classe quando o escopo já é válido na lesson.

IDCenárioDadoQuandoEntão
R1Inclusão pelo criadorNova EbdSessionUsuário cria sessãoAs classes incluídas são definidas pelo criador por seleção em lote
R2Fonte de classesClasses da igreja habilitadasCriação de sessãoClasses são lidas de platform/ministrys/{ministryId}/data/class_ref
IDCenárioDadoQuandoEntão
S1Assistente preenche classe vinculadaUsuário assistente da classeTenta preencher/revisar/concluirPermitido
S2Assistente fora da classeUsuário assistente não vinculado à classeTenta preencher/revisar/concluirNegado
S3Professor preenche classe vinculadaUsuário professor da classeTenta preencher/revisar/concluirPermitido
S4Superintendente envia igreja de responsabilidadeUsuário superintendente da igrejaTenta enviar relatório da igrejaPermitido
S5Superintendente fora da igrejaUsuário superintendente sem vínculo com a igreja alvoTenta enviarNegado
S6Governança devolve/aprovaSecretaria geral/coordenaçãoTenta devolver/aprovarPermitido
S7Secretaria local envia relatórioUsuário secretaria local da igreja de atuaçãoTenta enviar relatório da igrejaPermitido
IDCenárioDadoQuandoEntão
T1Totais gerais derivadosSessão com múltiplas classesSalva sessãoTotais da igreja = soma das classes
T2Sem campo manual conflitanteUsuário altera dados de classes após cálculo anteriorRecalcula totaisTotais gerais atualizados automaticamente
T3Professor com vínculo obrigatório na classe selecionadaUsuário professor sem vínculo na classe selecionadaTenta salvar preenchimento da classeNegado com erro de consistência
T4Assistente com vínculo obrigatório na classe selecionadaUsuário assistente sem vínculo na classe selecionadaTenta salvar preenchimento da classeNegado com erro de consistência

Quadro único — ações x fases x papéis

Section titled “Quadro único — ações x fases x papéis”

Legenda:

  • SIM = permitido
  • NAO = não permitido
  • COND = permitido com condição de escopo/fase
AçãoFase alvoAssistente (classe vinculada)Professor (classe vinculada)Superintendente (igreja responsável)Secretaria local (igreja de atuação)Secretaria geral / Coordenação ministérioCondição principal
Preencher dados da classeCREATED / IN_PROGRESSSIMSIMSIMSIMSIMClasse dentro do escopo do usuário
Revisar dados da classeIN_PROGRESSSIMSIMSIMSIMSIMClasse dentro do escopo do usuário
Concluir questionário da classeCONCLUDEDSIMSIMSIMSIMSIMVínculo obrigatório do papel com ao menos 1 classe
Fechar relatório da igrejaCLOSEDNAONAOSIMSIMSIMSessão em CONCLUDED e escopo válido
Reabrir fase antes do fechamento finalIN_PROGRESS / CONCLUDEDCONDCONDCONDCONDCONDPermitido conforme escopo e regra de governança
Editar após fechamentoCLOSEDNAONAONAONAOCONDSomente por reabertura explícita de governança
Solicitar adesãoCREATED / IN_PROGRESS / CONCLUDEDSIMSIMSIMSIMSIMBloqueado em CLOSED
Aprovar/rejeitar adesãoCREATED / IN_PROGRESS / CONCLUDEDCONDCONDCONDCONDCONDVer tabela “Quem aprova vinculação à classe”: prof. vinculado (só assistente), sup/sec local mesma unit, min./plat. admin

Notas obrigatórias:

  • Após CLOSED, papéis operacionais não podem mais alterar o relatório.
  • Reabertura de edição ocorre por governança (retorno para IN_PROGRESS).
  • Totais gerais da igreja são sempre derivados da soma das classes.
flowchart TD
A[Inicio] --> B{Sessao EBD existe para unidade/data?}
B -- Nao --> C[Criar sessao de EBD]
C --> C1[Definir classes da sessao]
C1 --> C2[Definir responsaveis EBD presentes]
C2 --> D[Fase: CREATED]
B -- Sim --> D
D --> E[Professor/Assistente preenchem classes vinculadas]
E --> F{Dados minimos por classe ok?}
F -- Nao --> E
F -- Sim --> G[Fase: IN_PROGRESS]
G --> H{Revisao aprovada no escopo?}
H -- Nao --> D
H -- Sim --> I[Fase: CONCLUDED]
I --> J{Ator pode fechar?}
J -- Superintendente ou Secretaria Local --> K[Fase: CLOSED]
J -- Secretaria Geral/Coordenacao --> K
J -- Nao --> I
K --> L{Governanca ministerial decide}
L -- Reabrir --> M[Fase: IN_PROGRESS]
M --> D
L -- Manter fechado --> N[Fase: CLOSED]
K --> O[Operacional bloqueado para editar]
N --> P[Fim]
  • Ação “Preencher relatório de EBD” filtrada por regra híbrida (minRole + matriz READ/FULL).
  • Navegação para EbdReportPage funcional.
  • Seleção de igreja (dropdown) com igreja do perfil pré-selecionada.
  • Seleção de data (apenas domingos).
  • GetOrCreateEbdSession: busca por unitId+date ou cria nova sessão.
  • Coleção platform/ministrys/{id}/data/ebds no Firestore.
  • Catálogo de classes em platform/ministrys/{id}/data/class_ref (1 documento por classe, com className, classDescription, enabled).
  • Classes como subcoleção: ebds/{sessionId}/lessons/{lessonId}.
  • Inclusão pelo criador: Quem cria a sessão define quais classes incluir por seleção em lote.
  • Sugestão na criação: Ao criar, classes da última EBD (mesma unidade) vêm pré-selecionadas, mantendo todas as demais visíveis.
  • Criação sem formulário operacional: na criação de sessão não há edição detalhada da classe (totais, observações, status operacional).
  • Lesson mínima na criação: classes entram com payload mínimo e status=CREATED.
  • Vínculo por classe na sessão: na gestão da sessão, cada classe pode ter múltiplos professores e múltiplos assistentes; atribuição é opcional.
  • Visão no preenchimento: no fluxo de classe, o usuário vê todas as classes da sessão; vínculo controla permissão de edição/salvamento por classe.
  • Adesão à classe: usuário operacional pode solicitar adesão por classe (TEACHER/ASSISTANT). Na UI, só aparecem opções de papel aprovadas no perfil (EBD_TEACHER / EBD_ASSISTENT em role_assignments); pré-seleção alinhada ao activeRole quando for um desses. Aprovação conforme tabela “Quem aprova vinculação à classe” (professor vinculado para assistente; superintendente ou secretário local da mesma igreja; administrador do ministério ou da plataforma; uso de role_assignments APPROVED).
  • Pendências comuns: solicitações de cargo e de adesão à classe compartilham a mesma lista de pendências (item tipado).
  • Responsáveis da sessão: multi seleção de pessoas elegíveis (EBD_SUPERINTENDENT, LOCAL_PASTOR, ASSISTANT_LOCAL_PASTOR, LOCAL_SECRETARY, EBD_SECRETARY).
  • Formulário da sessão exibe Tipo (classes de hoje), Clima, Temperatura, Observação; não exibe Status nem totais gerais.
  • Preenchimento operacional: no fluxo fill_ebd_class_report, o status da classe é sugerido como IN_PROGRESS.
  • Layout: totais de participantes no LessonFormCard em coluna (um campo abaixo do outro).
  • Totais gerais da igreja derivados da soma das classes.
  • Regras de fase e bloqueio pós-envio aplicadas.
  • Regras de escopo por vínculo/papel aplicadas.
  • Ações separadas de sessão e classe aplicadas no fluxo.
  • Cenários C1–C9, CL1–CL13 e CL6b–CL6f (UI/fluxo preenchimento), F1–F7, S1–S7, T1–T4 e R1–R2 cobertos por testes ou validação manual até automação.
  • Automação completa dos cenários de fase com auditoria.
  • UI dedicada para devolução/aprovação por governança.