Modelo de dados funcional
Introdução ao documento
Este documento descreve o modelo de dados observável localmente neste repositório. O escopo não é um schema relacional de banco, porque o projeto não expõe migrations, diretório schema ou ORM local; o que existe no código são:
- tipos de domínio em
src/types/*; - modelos utilitários em
src/models/*; - projeções e composições de runtime nos handlers BFF e hooks.
Por isso, o conteúdo abaixo representa um modelo contratual/runtime do frontend+BFF, não um DDL persistente do backend externo.
Evidências:
src/types/IClass.ts:42-86src/types/ITurma.ts:4-38src/types/IAppointment.ts:4-55src/types/ISubmission.ts:1-106src/models/MeetingRecover.ts:1-234src/models/ReasonOption.ts:1-5
Versionamento
Baseline derivado do estado atual do repositório em 2026-03-20. Este documento deve ser revisado quando houver mudança material em:
- tipos de domínio em
src/types/*; - composição de payloads nos handlers de
src/app/api/*; - mapeamentos de runtime em hooks e serviços BFF.
Evidências:
src/app/api/submissions/[id]/route.ts:4-84src/app/api/schedule/appointment/create/route.ts:10-77src/hooks/useSubmissions.ts:34-175src/app/services/bff/SubmissionService.ts:17-197
Referencial teórico
O documento usa três referências principais:
- modelagem contratual por tipos TypeScript;
- projeções de runtime consumidas pelas telas e hooks;
- notação Mermaid ERD para visualizar cardinalidade e chaves observadas.
Evidências:
src/types/IApiResponse.ts:1-6src/types/IParticipants.ts:1-25src/utils/mapSubmissionStatus.ts:3-15src/utils/createMissingActivities.ts:13-25
Escopo e fontes usadas
Fontes primárias efetivamente usadas
| Fonte | Papel no modelo | Evidência |
|---|---|---|
src/types/IClass.ts | Projeção resumida de turma/curso/ciclo usada no app protegido | src/types/IClass.ts:42-86 |
src/types/ITurma.ts | Detalhe de turma com lista de estudantes e consultorias | src/types/ITurma.ts:4-38 |
src/types/IStudent.ts | Participante no fluxo de presença | src/types/IStudent.ts:1-18 |
src/types/IParticipants.ts | Projeção de participante no fluxo de gestão de atividades | src/types/IParticipants.ts:1-25 |
src/types/ISubmission.ts | Entidades de submissão, arquivo e notificação | src/types/ISubmission.ts:1-106 |
src/types/IAppointment.ts | Entidades de agenda/agendamento | src/types/IAppointment.ts:4-55 |
src/types/ICycles.ts | Projeções de ciclo e turma por ciclo | src/types/ICycles.ts:1-27 |
src/types/IUser.ts | Projeção mínima de usuário retornado por backend | src/types/IUser.ts:1-10 |
src/types/next-auth.d.ts | Shape enriquecido de sessão no runtime | src/types/next-auth.d.ts:3-14 |
src/mocks/e2e-fixtures.ts | Exemplos concretos de payloads em execução E2E | src/mocks/e2e-fixtures.ts:221-560 |
Limitação de fonte
Não há schema relacional localmente formalizado; por isso, “PK”, “FK”, “unique” e cardinalidade abaixo significam papel observado no contrato e não constraint física comprovada em banco.
Evidências:
src/app/services/api.ts:115-244src/utils/consts.ts:1-11
Entidades/tabelas principais
| Entidade | Tipo local | Papel observado | Campos centrais observados | Evidência |
|---|---|---|---|---|
ClassData | agregação de turma | visão resumida de turma carregada no app protegido | id, title, slug, courses, ciclos, facilitator, facilitator_name, enable_calendar, enable_room, strategic_activities_number | src/types/IClass.ts:42-82 |
Course | detalhe de turma | visão detalhada de turma com alunos e consultorias | id, title, students, facilitator, start_date, end_date, first_consultancy, second_consultancy | src/types/ITurma.ts:4-25 |
Cycle | ciclo | ciclo retornado em listagens | id, name, slug, course_id, start_date, end_date, activities | src/types/ICycles.ts:1-16 |
ClassByClycleResponse | turma por ciclo | projeção simplificada de turma em listagens por ciclo | id, name, slug, cycle_id, turno | src/types/ICycles.ts:18-27 |
Student | participante de presença | aluno usado em presença e recuperação | id, name, cpf, activities, phone, enrollment_id, is_enroll_canceled, is_cancel_requested | src/types/IStudent.ts:1-18 |
Participant | participante de gestão de atividades | projeção usada no hook useSubmissions | id, name, cpf, email, activities[], is_enroll_canceled, is_cancel_requested | src/types/IParticipants.ts:1-25 |
SubmissionResponse | submissão | entrega/avaliação de atividade estratégica | id, participant_id, activity_id, class_id, course_id, cycle_id, facilitator_id, status, score, files[] | src/types/ISubmission.ts:11-27 |
SubmissionFile | arquivo de submissão | anexo vinculado a uma submissão | id, deliverable_submission_id, file_path, original_name, file_type | src/types/ISubmission.ts:1-9 |
Appointment | agendamento | slot/agendamento individual, grupo ou bloqueio | id, start_time, finish_time, class_id, type_id, client_id, employee_id, deleted_at | src/types/IAppointment.ts:4-28 |
Appointment.client | participante de agenda | participante associado ao agendamento | id, name, cpf, email, phone_number | src/types/IAppointment.ts:17-27 |
Appointment.employee | facilitador de agenda | facilitador associado ao agendamento | id, name, cpf, email, phone_number | src/types/IAppointment.ts:18-27 |
UserLogin | usuário mínimo | usuário retornado por consultas BFF específicas | ID, user_login, user_email, display_name | src/types/IUser.ts:1-10 |
RecoveryStatusResponse.data | status de recuperação | payload funcional de recuperação por encontro | user_id, class_id, cycle_id, collective_meeting_index, has_presence, recovery_deadline, recovery_video | src/models/MeetingRecover.ts:7-33 |
Relacionamentos e cardinalidade
As cardinalidades abaixo foram extraídas de chaves e coleções observadas no contrato. Quando o vínculo completo depende de backend externo, isso aparece na observação.
| Origem | Destino | Cardinalidade observada | Base | Evidência |
|---|---|---|---|---|
ClassData | CourseInfo embutido em courses | N:1 inferência operacional | cada ClassData contém um único courses, identificado por courses.id | src/types/IClass.ts:12-26, src/types/IClass.ts:42-56 |
ClassData | CycleInfo embutido em ciclos | N:1 inferência operacional | cada ClassData contém um único ciclos, identificado por ciclos.id | src/types/IClass.ts:28-35, src/types/IClass.ts:42-56 |
Course | Student[] | 1:N fato observado | o detalhe de turma expõe students: Student[] | src/types/ITurma.ts:4-10 |
ClassData | Student[] | 1:N fato observado | a rota de presença é indexada por class_id e retorna lista de alunos | src/app/services/external/ClassService.ts:223-234, src/app/api/presence/[id]/route.ts:19-24 |
ClassData | Participant[] | 1:N projeção de runtime | useSubmissions carrega participantes por turma e os enriquece com submissões | src/hooks/useSubmissions.ts:51-127 |
SubmissionResponse | SubmissionFile[] | 1:N fato observado | a submissão contém files: SubmissionFile[] | src/types/ISubmission.ts:11-27 |
SubmissionResponse | Participant | N:1 fato observado | participant_id vincula a submissão a um participante | src/types/ISubmission.ts:11-27, src/hooks/useSubmissions.ts:81-103 |
SubmissionResponse | ClassData | N:1 fato observado | class_id vincula a submissão à turma | src/types/ISubmission.ts:11-27 |
SubmissionResponse | CourseInfo | N:1 fato observado | course_id vincula a submissão ao curso | src/types/ISubmission.ts:11-27 |
SubmissionResponse | CycleInfo/Cycle | N:1 fato observado | cycle_id vincula a submissão ao ciclo | src/types/ISubmission.ts:11-27, src/types/ICycles.ts:1-16 |
SubmissionResponse | Facilitator | N:1 fato observado | facilitator_id é propagado na criação e no contrato de submissão | src/types/ISubmission.ts:11-27, src/components/EnvioDeAtividades/components/Upload.component.tsx:165-176 |
Appointment | ClassData | N:1 fato observado | class_id identifica a turma do agendamento | src/types/IAppointment.ts:4-16 |
Appointment | Appointment.client | N:0..1 fato observado | client pode ser null em bloqueios/grupos | src/types/IAppointment.ts:13-18, src/mocks/e2e-fixtures.ts:405-417 |
Appointment | Appointment.employee | N:1 fato observado | todo agendamento tem employee | src/types/IAppointment.ts:18-27 |
RecoveryStatusResponse.data | ClassData | N:1 fato observado | class_id liga o status de recuperação à turma | src/models/MeetingRecover.ts:7-26 |
RecoveryStatusResponse.data | Cycle | N:1 fato observado | cycle_id liga o status de recuperação ao ciclo | src/models/MeetingRecover.ts:7-26 |
Campos críticos
Identificadores e chaves observadas
| Entidade | Campo | Papel observado | Evidência |
|---|---|---|---|
ClassData | id | PK observada no contrato de turma | src/types/IClass.ts:50-53 |
Course | id | PK observada no detalhe de turma | src/types/ITurma.ts:4-7 |
Cycle | id | PK observada no contrato de ciclo | src/types/ICycles.ts:1-5 |
ClassByClycleResponse | id | PK observada em listagem por ciclo | src/types/ICycles.ts:18-22 |
Student | id | PK observada do aluno em presença | src/types/IStudent.ts:6-8 |
Participant | id | PK observada da projeção de gestão de atividades | src/types/IParticipants.ts:4-8 |
SubmissionResponse | id | PK observada da submissão | src/types/ISubmission.ts:11-14 |
SubmissionFile | id | PK observada do arquivo | src/types/ISubmission.ts:1-4 |
SubmissionFile | deliverable_submission_id | FK observada para submissão | src/types/ISubmission.ts:1-9 |
Appointment | id | PK observada do agendamento | src/types/IAppointment.ts:4-16 |
Appointment | class_id | FK observada para turma | src/types/IAppointment.ts:9-12 |
Appointment | client_id | FK observada para cliente/participante | src/types/IAppointment.ts:11-16 |
Appointment | employee_id | FK observada para facilitador | src/types/IAppointment.ts:12-16 |
Status, flags e timestamps
| Entidade | Campo | Semântica observada | Evidência |
|---|---|---|---|
SubmissionResponse | status | estado de entrega/avaliação | src/types/ISubmission.ts:25-27 |
SubmissionResponse | score | nota da avaliação | src/types/ISubmission.ts:20-21 |
SubmissionResponse | evaluated_at | timestamp de avaliação | src/types/ISubmission.ts:20-24 |
SubmissionResponse | created_at, updated_at | timestamps de criação/atualização | src/types/ISubmission.ts:22-24 |
SubmissionFile | created_at, updated_at | timestamps do anexo | src/types/ISubmission.ts:6-9 |
Appointment | created_at, updated_at, deleted_at | timestamps de ciclo de vida; deleted_at sugere soft delete | src/types/IAppointment.ts:14-16 |
Student | is_enroll_canceled, is_cancel_requested | flags de cancelamento | src/types/IStudent.ts:12-15 |
ClassData | enable_calendar, enable_room, enable_strategic_activities, is_recovery_enabled | flags de feature de turma | src/types/IClass.ts:43-44, src/types/IClass.ts:66-82 |
RecoveryStatusResponse.data | has_presence, recovery_needed, recovery_expired | estado funcional de recuperação | src/models/MeetingRecover.ts:16-26 |
Unique
Constraint unique não foi comprovada localmente em nenhuma entidade por ausência de migrations/schema físico. Há apenas chaves observadas no contrato.
Evidências:
src/types/ISubmission.ts:11-27src/types/IAppointment.ts:4-28src/types/IClass.ts:42-82
Constraints e enums
| Domínio | Campo | Valores observados | Evidência |
|---|---|---|---|
SubmissionResponse | status | pending, submitted, evaluated, submitted_external | src/types/ISubmission.ts:25-27, src/types/ISubmission.ts:44-55 |
Participant.activities[] | status | avaliada, recebida, não recebida, recebida em outro canal | src/types/IParticipants.ts:9-25 |
| Mapeamento runtime | Submission.status -> ActivityStatus | evaluated -> avaliada, submitted -> recebida, pending -> não recebida, submitted_external -> recebida em outro canal | src/utils/mapSubmissionStatus.ts:3-15 |
Appointment | type_id | `1 | 2 |
Appointment mock | type_id semântica observada | 1 = bloqueio, 3 = individual, 4 = grupo | src/mocks/e2e-fixtures.ts:367-367, src/mocks/e2e-fixtures.ts:405-405, src/mocks/e2e-fixtures.ts:1069-1071 |
Turno | value | diurno, noturno, vespertino, unica | src/types/IClass.ts:37-40, src/types/ITurma.ts:14-17, src/types/ICycles.ts:23-26 |
MeetingStatus | status | available, progress, done | src/models/MeetingRecover.ts:1-5 |
Divergências entre modelo e código de runtime
| Divergência | Tipo/Modelo | Runtime observado | Impacto | Evidência |
|---|---|---|---|---|
| Projeção de participante muda de shape entre presença e gestão de atividades | Student.activities é Record<string, boolean> | Participant.activities é lista com status, id?, activity_id; useSubmissions junta participantes com submissões para construir essa visão | mesmo conceito funcional aparece em dois formatos distintos | src/types/IStudent.ts:1-18, src/types/IParticipants.ts:1-25, src/hooks/useSubmissions.ts:81-127 |
BFF de participantes retorna fonte de presença, mas o consumidor tipa Participant[] | rota usa getPresenceByClassId | getParticipants() promete Participant[] | possível descompasso entre contrato do endpoint e shape consumido | src/app/api/submissions/class/[id]/route.ts:22-27, src/app/services/bff/SubmissionService.ts:151-155 |
CreateAppointment.employee_id é numérico no tipo | o handler injeta facilitador.cpf em employee_id | campo sai como string/CPF ao montar o payload do upstream | incompatibilidade entre tipo local e payload efetivo enviado | src/types/IAppointment.ts:43-50, src/app/api/schedule/appointment/create/route.ts:54-60 |
| Facilitador muda de shape entre resumo e detalhe de turma | ClassData.facilitator é id numérico, com facilitator_name e facilitator_email separados | Course.facilitator é objeto completo Facilitator | a entidade “facilitador” não é uniforme entre projeções | src/types/IClass.ts:69-73, src/types/ITurma.ts:4-10, src/types/IFacilitador.ts:2-10 |
Ciclo muda de tipo no campo activities | Cycle.activities é string | ClassData.ciclos.activities é number; fixture também usa número | divergência de tipagem entre projeções do mesmo domínio | src/types/ICycles.ts:1-10, src/types/IClass.ts:28-35, src/mocks/e2e-fixtures.ts:466-473 |
| Usuário consultado e sessão autenticada não compartilham o mesmo contrato | UserLogin é mínimo | Session.user e payload de login carregam token, role, user_display_name, user_first_name, user_last_name, possivelmente enroll_ids | o modelo de usuário de runtime é mais rico que o tipo de consulta BFF | src/types/IUser.ts:1-10, src/types/next-auth.d.ts:3-14, src/utils/authOptions.ts:69-87 |
Pendências
- Não há migrations, DDL, schema Prisma/Sequelize/TypeORM ou modelos persistentes locais; portanto não foi possível comprovar constraints físicas de banco,
uniquereais,on delete, índices ou nomes de tabelas. ClassData,CourseeCyclesão projeções de API externa e não um modelo relacional único; o acoplamento exato entre essas estruturas depende do backend WordPress.- A rota
GET /api/submissions/{id}é consumida por serviço BFF, mas não está implementada no handler local; isso impede validar um modelo canônico de “submissão unitária”. Evidência:src/app/services/bff/SubmissionService.ts:43-47,src/app/api/submissions/[id]/route.ts:4-84. - O payload de recuperação depende de backend externo e ainda contém a divergência
class_iddno proxy local. Evidência:src/app/api/cycles/recovery-status/route.ts:38-46.
ERD Mermaid
Evidências do ERD:
src/types/IClass.ts:42-82src/types/ITurma.ts:4-25src/types/IStudent.ts:6-18src/types/IParticipants.ts:1-25src/types/ISubmission.ts:1-106src/types/IAppointment.ts:4-55src/models/MeetingRecover.ts:7-33