Documentação CAE

Técnica & Operacional · 9 documentos

Documentação Técnica — CAE

CAE — Centro de Apoio ao Estudante é um ecossistema digital que centraliza a gestão académica, os serviços ao estudante, as operações escolares e uma rede B2B de refeitórios e fornecedores, numa única plataforma moderna.

Domínio público: https://caeao.com · App publicada em https://cae-smart-campus.base44.app

Índice

| Documento | Conteúdo | | --- | --- | | 01 — Visão Geral e Arquitetura | Missão, stack técnico, portais, papéis e fluxos de alto nível | | 02 — Modelo de Dados | Catálogo de entidades, agrupadas por domínio, com schema e regras RLS | | 03 — Backend | Funções de backend, workflows agendados/acionados e módulos partilhados | | 04 — Frontend | Rotas e páginas, sistema de design (tokens, tipografia, utilitários) | | 05 — Segurança e Fluxos | Autenticação, RLS, fluxo de pagamentos em duas fases, notificações automáticas | | 06 — Manual Operacional | Operações por domínio: onboarding, subscrição/carteira/cartão, académico, feed, salas, eventos, refeitório, fornecedores, marketplace, Twisco, comunicações | | 07 — Regras e Configuração | Constantes de negócio: preços, PTT, CAE Score, categorias, estados, notificações | | 08 — Gestão e Responsabilidades | Matriz RACI, operações automáticas, publicação, erros conhecidos, dívida técnica, manutenção |

Stack técnico

  • Frontend: React 18 + Vite (ESM), Tailwind CSS, shadcn/ui, React Router, TanStack Query, Framer Motion, Recharts, lucide-react, react-leaflet, three.js, react-quill, @hello-pangea/dnd.
  • Tipografia: Space Grotesk (toda a plataforma) e Inter (apenas landing page), via @import no src/index.css.
  • Backend: Base44 (backend-as-a-service): entidades (JSON Schema), funções (base44/functions/<nome>/entry.ts), workflows (base44/workflows/*.jsonc), integrações Core (LLM, e-mail, uploads, voz, vídeo, imagem).
  • SDK: @/api/base44Client (cliente Base44 pré-inicializado) — entidades em base44.entities.<Entidade>, integrações em base44.integrations.Core.*, auth em base44.auth.*.
  • Auth: gerida pela plataforma (sessões, OTP, reset, OAuth Google). A app adiciona fluxos próprios: acesso do painel financeiro por utilizador/senha, primeiro acesso por token, login por username/telemóvel.
  • Região/idioma: Angola (Kwanza Kz e PTT como moedas internas), interface em português de Angola, fuso Africa/Luanda.

Portais (isolados)

A plataforma está dividida em portais com separação total de dados e navegação:

| Portal | Rota base | Utilizadores | | --- | --- | --- | | Nacional (CAE) | /nacional | Admin e Gestor | | Escola | /escola | Contas de escola | | Estudante | /estudante | Estudantes | | Professor | /professor | Professores | | Encarregado | /encarregado | Encarregados de educação | | Refeitório | /refeitorio | Operadores de refeitório | | Fornecedor | /fornecedor | Fornecedores B2B | | Parceiro | /parceiro | Parceiros de serviços | | Financeiro | /financeiro | Contabilidade & Finanças (auth própria) |

Papéis

  • admin — gestão total da plataforma (acesso a todos os painéis nacionais).
  • gestor — gestor nacional com secções configuráveis (national_permissions no User); paridade de permissões com o admin nas operações de gestão.
  • user — estudantes, professores, encarregados e contas de entidades (escolas, parceiros, fornecedores, refeitórios). O campo user_type distingue o sub-perfil (escola, parceiro, nacional, etc.) e direciona o login para o portal correto.

Princípios de desenho

  1. Separar ecossistema escolar do B2B refeitório/fornecedor — notificações e dados têm portal explícito; o sino só mostra o do portal ativo.
  2. Tudo em Kz, com PTT como carteira interna paralela.
  3. Validação de pagamentos em duas fases — Contabilidade/Finanças valida o comprovativo; só depois Admin/Gestor aprova/rejeita.
  4. Notificações automáticas (Bom dia, Palavras sábias, Boa noite) com validade de 24h e expiração automática.
  5. Sem perfis futuros / IA-centric no marketing — tom corporativo, humano e profissional.

01 — Visão Geral e Arquitetura

Missão

O CAE centraliza, para o ecossistema educativo angolano:

  • gestão académica (escolas, turmas, notas, presenças, trabalhos, ocorrências);
  • serviços ao estudante (cartão CAE, carteira PTT, refeitório, salas de estudo, feed académico, eventos, marketplace);
  • uma rede B2B de refeitórios e fornecedores (produtos, encomendas, stock, campanhas de abastecimento);
  • comunicação multi-canal (comunicados nacionais/escolares, notificações automáticas, e-mail);
  • gestão financeira (assinaturas, carregamentos PTT, contabilidade).

Arquitetura de alto nível

┌─────────────────────────────────────────────────────────────┐
│  Frontend (React + Vite) — src/pages, src/components         │
│  9 portais isolados · auth pela plataforma · SDK @/api/base44Client │
└───────────────┬─────────────────────────────────────────────┘
                │  base44.entities.*  ·  base44.functions.invoke  ·  base44.integrations.Core.*
┌───────────────▼─────────────────────────────────────────────┐
│  Base44 Backend                                              │
│  ├─ Entidades (JSON Schema + RLS)                            │
│  ├─ Funções (base44/functions/*/entry.ts) — HTTP handlers    │
│  ├─ Workflows (base44/workflows/*.jsonc) — agendados/acionados│
│  ├─ Integrações Core (LLM, SendEmail, Uploads, Voz, Vídeo)   │
│  └─ Módulos partilhados (base44/shared/*.ts)                 │
└─────────────────────────────────────────────────────────────┘

Camadas

  • Frontend — cada portal é um *Dashboard.jsx (layout + sidebar) com páginas-filhas em src/pages/<portal>/. Componentes reutilizáveis em src/components/ e src/components/ui/ (shadcn).
  • Entidades — fonte de verdade persistida; cada uma tem rls que regista quem cria/lê/atualiza/elimina.
  • Funções de backend — HTTP handlers para lógica que o cliente não deve/pode fazer: operações privilegiadas (service role), agregações pesadas, integrações externas, fluxos multi-passo (adesão, pagamento, inscrição em eventos, eliminação em cascata).
  • Workflows — automações acionadas por entidade (create/update) ou por agendamento (cron/intervalo), que chamam funções de backend.
  • Partilhados — base44/shared/*.ts reutilizam lógica entre funções (pagamentos, notificações, finanças, destinatários de e-mail, auto-notificações).

Fluxos principais (resumo)

Adesão de uma entidade (escola/parceiro/refeitório/fornecedor)

  1. Admin convida → AccountSetupToken (token + código de 6 dígitos, 24h).
  2. Convite enviado por e-mail; o destinatário abre /primeiro-acesso, insere o código → verifyAccessCode.
  3. Define senha → setupAccountPassword → conta User criada/ativada.
  4. No primeiro login → completeAccountSetup liga a entidade (por e-mail) ao User e define user_type → resolveLoginIdentifier encaminha ao portal certo.

Pagamento (assinatura ou carregamento PTT)

  1. Estudante/encarregado submete comprovativo → cria SubscriptionPayment/PTTTopupRequest com status=pendente, finance_status=aguardando.
  2. notifyPaymentPending avisa Admin/Gestor (in-app + e-mail).
  3. Contabilidade & Finanças valida o comprovativo → finance_status=aprovado|rejeitado (financeAuth sessão própria).
  4. Só com finance_status=aprovado é que Admin/Gestor pode aprovar/rejeitar final (status). Na aprovação: define subscription_start/end, credita PTT (se carregamento) — ver 05 — Segurança e Fluxos.

Comunicado nacional

  1. Admin/Gestor cria Announcement (scope=nacional, targets=[...]).
  2. Workflow Distribute Announcement Notifications aciona distributeAnnouncementNotifications → cria Notification por utilizador dos painéis-alvo + envia e-mail (em lotes) aos destinatários autorizados.
  3. (Eliminação) Admin/Gestor pode eliminar o comunicado → remove também as Notification distribuídas.

Notificações automáticas

  • Workflow Notificações Automáticas corre a cada 5 min → runAutoNotifications envia as mensagens do horário atual (bom dia 08:00, palavras sábias 12:00, boa noite 20:00) + cleanupAutoNotifications remove as que passaram das 24h. Ver 05.

Notificar encarregados

  • Workflows acionados por Grade, Attendance, Assignment, PTTTransaction, Announcement (create) e Student (update de card_status) chamam guardianNotify, que cria notificação para os encarregados ligados ao estudante.

Convenções de código

  • Imports: alias @/ (nunca caminhos relativos para src/).
  • shadcn/ui: cada primitiva importa-se do seu próprio ficheiro em @/components/ui/.
  • cn vem de @/lib/utils; createPageUrl de @/utils.
  • Classes Tailwind: literais em strings (o build purga dinâmicas); safelist só para valores em runtime.
  • Entidades: filtro/count/aggregate no servidor; lê-se .items das páginas (nunca tratar como array).
  • Erros: deixam-se propagar, exceto fluxos de utilizador (forms/auth) que mostram erro inline.

02 — Modelo de Dados

As entidades são JSON Schemas em base44/entities/<Nome>.jsonc. Todos os registos têm automaticamente id, created_date, updated_date, created_by_id (não se declaram). As regras de acesso (RLS) vivem na chave rls de cada entidade (ver 05 — Segurança).

Catálogo por domínio

Identidade & acesso

| Entidade | Descrição | | --- | --- | | User (built-in) | Conta de acesso. Campos editáveis: role (admin/gestor/user), user_type (escola/parceiro/nacional…), national_permissions, phone, full_name. Só a plataforma cria utilizadores (convites). | | FinanceAccount | Acesso ao painel Financeiro por username + senha (sem e-mail). password_hash/password_salt (PBKDF2-SHA256), session_token/session_expires_at. RLS: admin/gestor. | | AccountSetupToken | Token + código de 6 dígitos para adesão de entidades (24h). RLS: admin. | | GestorActivity | Registo de auditoria das ações de cada gestor. Leitura: próprio ou admin. |

Académico escolar

| Entidade | Descrição | | --- | --- | | School | Escola registada; owner_user_id liga à conta de acesso. | | ClassRoom | Turma de uma escola. | | Student | Estudante. Campos-chave: student_id_code, card_number, qr_token, card_status, ptt_balance, subscription_status (trial/assinatura), guardian_user_ids[], school_id. | | Teacher | Professor; created_by_id liga à conta. | | Grade / StudentScore | Notas e pontuação CAE. | | Attendance | Registos de presença. | | Assignment / AssignmentSubmission | Trabalhos e entregas. | | Occurrence | Ocorrências disciplinares. | | Complaint | Reclamações. | | SchoolConfig | Configuração académica por escola (classe, período, ano letivo, disciplina, curso). | | SchoolEvent / ScheduleItem | Eventos escolares e itens de horário. |

Comunicação

| Entidade | Descrição | | --- | --- | | Announcement | Comunicado. scope (escola/nacional), target (escola) e targets[] (nacional: painéis destinatários), type (aviso/comunicado/evento/urgente). RLS: leitura aberta, criação aberta, update/delete só admin/gestor. | | AnnouncementRead | Marca de leitura (user_id == próprio). | | Notification | Notificação do sino. user_id, type, portal (escola/refeitorio/fornecedor), source (automatico), auto_category, related_entity_id, expires_at. RLS: próprio ou admin/gestor. | | Message | Mensagens diretas (sender_id/receiver_id). | | AcademicPost / AcademicComment / AcademicReaction | Feed académico (resumos, exercícios, etc.) + reações educativas (Excelente, Muito Bom, Inteligente, Muito Útil, Boa Ideia, Criativo, Inspirador). visibility controla audiência (turma/classe/nível/escola). |

Notificações automáticas (Bom dia / Palavras sábias / Boa noite)

| Entidade | Descrição | | --- | --- | | AutoNotificationSettings | Registo único (key="default"): timezone, paused, ai_enabled, slots (por categoria: enabled/hour/minute/weekdays/inapp/email/start_date/end_date). RLS: admin/gestor. | | AutoNotificationMessage | Biblioteca de mensagens aprovadas (category, theme, title, content, author, status, source biblioteca/ia, times_used). RLS: admin/gestor. | | AutoNotificationPreference | Preferências por utilizador (canais, horários pessoais, período de silêncio). RLS: próprio ou admin/gestor. | | AutoNotificationLog | Log de cada envio/limpeza (dedupe_key impede duplicações, status entregue/parcial/falhou). RLS: admin/gestor. |

Eventos

| Entidade | Descrição | | --- | --- | | Event | Evento nacional/escolar (data, local, pagamento gratuito/kwanza/ptt/combinado). | | EventRegistration | Inscrição/bilhete: qr_token, validation_code, ticket_code, payment_type, checked_in. RLS: create admin/gestor (via função registerForEvent), leitura aberta. | | EventReview | Avaliação de evento. | | ScanLog | Registo de leituras de QR (cartão/bilhete/pedido). |

Refeitório (consumidor B2C)

| Entidade | Descrição | | --- | --- | | Refectory | Refeitório; user_id liga à conta. | | SchoolRefectoryLink | Ligação escola ↔ refeitório. | | Meal | Refeição/produto servido. | | Order | Pedido de refeitório (pago por PTT/Kz). | | MealReview / RefectoryReview | Avaliações (item_type distingue produto vs refeição). | | WalletConfig | Configuração da carteira/conversões. |

Fornecedores (B2B)

| Entidade | Descrição | | --- | --- | | CafeteriaSupplier | Fornecedor B2B; user_id liga à conta. | | SupplierProduct / Product | Catálogo de produtos. | | SupplierOrder / SupplyOrder | Encomendas (refeitório→fornecedor / fornecedor→refeitório). | | SupplyCampaign | Campanha de abastecimento. | | StockItem / StockMovement | Stock e movimentos. | | CafeteriaExpense | Despesas de refeitório. | | ProductReview | Avaliação de produto. |

Marketplace & Parceiros

| Entidade | Descrição | | --- | --- | | Partner | Parceiro de serviços; owner_user_id. | | Professional | Profissional ligado a um parceiro. | | Service / Booking | Serviços e reservas. | | MarketplaceItem / MarketOrder / CartItem / Favorite | Itens de marketplace, encomendas, carrinho, favoritos. | | MarketplaceReview | Avaliação de marketplace. |

Financeiro

| Entidade | Descrição | | --- | --- | | SubscriptionPayment | Pagamento de assinatura/cartão. status (pendente/aprovado/rejeitado) + finance_status (aguardando/aprovado/rejeitado) — duas fases. RLS de update obriga finance_status já decidido para admin/gestor aprovarem. | | PTTTopupRequest | Carregamento PTT (mesmo padrão de duas fases). credited evita duplo crédito. | | PTTTransaction | Movimentos da carteira PTT. | | PaymentConfig | Configuração de pagamentos (IBAN, valores dos planos). | | CardHistory | Histórico do cartão CAE. |

Salas de estudo

| Entidade | Descrição | | --- | --- | | StudyRoom | Sala (delegado, disciplina, código de convite, link partilhável). | | StudyRoomMember / StudyRoomMaterial / StudyRoomMessage / StudyRoomTask / StudyRoomEvent | Membros, materiais, mensagens, tarefas, eventos da sala. | | StudyConversation / StudyMessage | Conversas/mensagens de estudo privadas. | | StudySession / StudyTask / StudyEvent / ScheduleItem | Sessões, tarefas e eventos de estudo pessoal. |

Twisco (concurso)

| Entidade | Descrição | | --- | --- | | TwiscoConfig / TwiscoCandidate / TwiscoVote | Configuração, candidatos e votos do concurso Twisco. |

Entidades detalhadas (schemas completas)

As schemas completas das entidades mais centrais estão no repositório em base44/entities/<Nome>.jsonc. Os exemplos abaixo resumem os campos principais.

Student

full_name*, username, date_of_birth, bi_number, phone, phone_country_code, email, photo_url,
school_id, school_name, class_name, grade, shift, academic_year,
guardian_name, guardian_phone, guardian_relation, guardian_user_ids[],
province, municipality,
status (pendente/activo/candidato/suspenso/graduado/desistente),
card_status (pendente/aprovado/impresso/pronto/entregue/reemitido/cancelado),
card_number, student_id_code, qr_token, card_issued_date, last_validated_date,
ptt_balance, enrollment_status,
trial_start, trial_end, trial_12h_notification_sent,
subscription_status (trial_active/trial_expired/payment_pending/payment_rejected/subscription_active/subscription_expired),
selected_plan, subscription_start, subscription_end, physical_card_requested

RLS: delete só admin/gestor (restantes abertos — verificado por checkStudentAccess).

Notification

user_id*, type* (enum 16 tipos), title*, message, is_read, link_url,
related_entity_id, portal (escola/refeitorio/fornecedor),
source, auto_category (bom_dia/palavras_sabias/boa_noite), expires_at

RLS: create aberto; read/update/delete — próprio ou admin/gestor.

SubscriptionPayment / PTTTopupRequest (duas fases)

student_id*, student_name, student_user_id, plan/amount_ptt, amount_kz, total_amount,
comprovativo_url, comprovativo_name,
status* (pendente/aprovado/rejeitado),            # decisão final Admin/Gestor
finance_status (aguardando/aprovado/rejeitado),   # 1.ª fase — Contabilidade
finance_validated_by_name, finance_validated_at, finance_observation,
validated_by_id, validated_by_name, validated_at, admin_observation, rejection_reason,
subscription_start/end (assinatura), credited (PTT)

RLS de update (admin/gestor): exige finance_status ∈ {aprovado,rejeitado} — garante a ordem das duas fases.

Notas de modelação

  • Não armazenar conteúdo grande (base64, PDFs) em campos — uploads via UploadPrivateFile, guarda-se o file_uri.
  • Campos de ligação usam sempre IDs (school_id, student_user_id, created_by_id); created_by_id é a âncora fiável de propriedade.
  • phone normalizado em formato xxx xxx xxx; validação de unicidade via checkPhoneExists.

03 — Backend

Funções de backend

Ficheiros em base44/functions/<nome>/entry.ts. Cada um é um handler HTTP export default async (req). Invocam-se pelo SDK (base44.functions.invoke('<nome>', payload)) ou por HTTP em https://cae-smart-campus.base44.app/functions/<nome>. Usam createClientFromRequest(req) para obter o cliente (app user) e base44.asServiceRole para operações privilegiadas que contornam a RLS.

Identidade, adesão e acesso

| Função | Auth | Descrição | | --- | --- | --- | | checkAdesaoEmail | pública | Verifica se um e-mail já tem conta User ({ exists }). Usado nos formulários de adesão. | | checkPhoneExists | pública | Verifica unicidade de telemóvel em todas as contas (normaliza dígitos). | | resolveLoginIdentifier | app user | Resolve username/telemóvel/e-mail → e-mail canónico para login (suporta login por nome de utilizador ou telefone). | | verifyAccessCode | app user | Valida o código de 6 dígitos de um AccountSetupToken (adesão de entidade). | | setupAccountPassword | app user | Define a senha da conta a partir do token de adesão. | | completeAccountSetup | app user | No primeiro login: liga a entidade (School/Refectory/CafeteriaSupplier/Partner) ao User por e-mail e define user_type (escola/parceiro/nacional). Promove gestor se for token de gestor. | | provisionEntityAccount | admin/gestor | Cria a entidade + gera AccountSetupToken + envia convite por e-mail. | | deleteLinkedUser | admin/gestor | Revoga a conta User ligada a uma entidade (procura por e-mail se não houver user_id). Usa service role. | | deleteStudent | admin/gestor | Eliminação em cascata de um estudante: remove Student + todos os registos académicos, financeiros, de cartão, refeitório, sala de estudo, conversas/mensagens, notificações e a conta User (por e-mail). Listas BY_STUDENT e BY_USER mapeiam cada entidade ao campo de ligação. |

Gestão nacional e financeira

| Função | Auth | Descrição | | --- | --- | --- | | manageGestores | admin/gestor | CRUD de gestores nacionais: list (gestores + candidatos), promote, demote, setPermissions. Usa service role para ler/atualizar User. | | manageFinanceAccounts | admin/gestor | CRUD de acessos ao painel Financeiro: list/create/update/remove. Gera hash PBKDF2 via createCredentials; reset de senha limpa a sessão. | | financeAuth | (pública, login próprio) | Autenticação do painel Financeiro por username+senha: verifica hash, emite session_token com expiração. | | financeData | sessão finance | Dados de relatórios/validação para o painel Financeiro (comprovativos, entradas, conversões). | | resetPlatformData | admin | Repõe dados de teste/configuração da plataforma. | | listGuardians | escola/admin | Lista encarregados ligados aos estudantes de uma escola. |

Pagamentos

| Função | Auth | Descrição | | --- | --- | --- | | notifyPaymentPending | dono ou admin/gestor | Avisa Admin/Gestor (in-app + e-mail) de um novo SubscriptionPayment (source=assinatura) ou PTTTopupRequest (source=carregamento) aguardando Contabilidade. Usa notifyPaymentSubmitted do paymentFlow.ts. | | processSubscriptions | agendada | Processa testes gratuitos (expira 24h, notifica 12h antes) e expira assinaturas. PLAN_DURATION = {trimestral:3, semestral:6, anual:12}. |

Eventos

| Função | Auth | Descrição | | --- | --- | --- | | registerForEvent | app user | Inscrição em evento: valida vaga, gere bilhete (qr_token, validation_code, ticket_code); se pago em Kz/PTT valida e debita ptt_balance do estudante; cria EventRegistration. | | distributeEventNotifications | workflow | Notifica participantes/painéis sobre inscrição, publicação ou cancelamento de evento. |

Comunicação e notificações

| Função | Auth | Descrição | | --- | --- | --- | | distributeAnnouncementNotifications | workflow | Distribui um Announcement nacional: mapeia targets[] → utilizadores de cada painel (panelUserIds), cria Notification por destinatário (sem duplicar), e envia e-mail em lotes (EMAIL_BATCH=6) aos autorizados (canReceiveCaeEmail). | | guardianNotify | workflow | Cria notificação para os encarregados (guardian_user_ids) de um estudante sobre nota/presença/trabalho/comunicado/PTT/cartão. | | runAutoNotifications | agendada | Envia as mensagens automáticas do horário atual (bom dia/palavras sábias/boa noite): lê settings, preferências, escolhe mensagem aprovada da biblioteca, personaliza {{nome}}, entrega in-app + e-mail, regista em AutoNotificationLog com dedupe_key. | | cleanupAutoNotifications | admin/gestor | Remove as notificações automáticas que passaram das 24h de validade (cleanupExpiredNotifications). | | manageAutoNotifications | admin/gestor | Ações administrativas: testar envio, executar agora, gerar mensagens com IA (generateMessagesWithAI). |

Académico

| Função | Auth | Descrição | | --- | --- | --- | | checkStudentAccess | app user | Verifica/actualiza o estado de acesso do estudante (auto-expira teste/assinatura) e devolve hasAccess, datas e plano. | | schoolAssistant | app user | Assistente de escola (LLM) para apoio a operações escolares. |

Workflows

Ficheiros em base44/workflows/*.jsonc (CNCF Serverless Workflow DSL). Cada workflow tem trigger (entity/scheduled) + definition.do[] (passos invoke_backend_function).

Acionados por entidade

| Workflow | Acionador | Chama | | --- | --- | --- | | Distribute Announcement Notifications | Announcement create | distributeAnnouncementNotifications | | Notificar Encarregados — Comunicado | Announcement create | guardianNotify | | Notificar Encarregados — Nova Nota | Grade create | guardianNotify | | Notificar Encarregados — Presença | Attendance create | guardianNotify | | Notificar Encarregados — Novo Trabalho | Assignment create | guardianNotify | | Notificar Encarregados — PTT | PTTTransaction create | guardianNotify | | Notificar Encarregados — Cartão CAE | Student update (changed_fields inclui card_status) | guardianNotify | | Notificar Inscrição em Evento | EventRegistration create | distributeEventNotifications | | Notificar Publicação/Cancelamento de Evento | Event update (changed_fields inclui status) | distributeEventNotifications |

Agendados

| Workflow | Cadência | Faz | | --- | --- | --- | | Notificações Automáticas | cron */5 * * * * (Luanda) | runAutoNotifications → cleanupAutoNotifications | | Process Student Subscriptions | intervalo 15 min | processSubscriptions (expira testes/assinaturas) |

Módulos partilhados (base44/shared/*.ts)

| Módulo | Descrição | | --- | --- | | autoNotifications.ts | Núcleo das notificações automáticas: CATEGORIES, DEFAULT_SLOTS (08:00/12:00/20:00), luandaParts, slotDue (janela de 6 min), buildDelivery, pickMessage, loadSettings/loadUsers/loadPreferences, generateMessagesWithAI, cleanupExpiredNotifications. TTL 24h, máx. 3 tentativas, lotes de e-mail de 6. | | paymentFlow.ts | Estado e etiquetas de pagamento + notifyPaymentSubmitted/notifyFinanceDecision (notifica Admin/Gestor in-app + e-mail respeitando o allowlist). | | notificationRecipients.ts | CAE_EMAIL_RECIPIENTS (allowlist de e-mails admin/gestor autorizados a receber e-mails CAE) + canReceiveCaeEmail. | | finance.ts | normalizeUsername, createCredentials (PBKDF2-SHA256), asList — usados pelo auth/CRUD do painel financeiro. |

Integrações Core usadas

  • SendEmail — comunicados, notificações automáticas, validação de contabilidade, notificação de pagamentos, expiração de testes (com anexos opcional).
  • InvokeLLM — schoolAssistant, geração de mensagens automáticas (gemini_3_flash quando necessário), assistentes do feed.
  • UploadPrivateFile — comprovativos de pagamento, fotos de perfil/estudante, materiais. (Os ficheiros são armazenados privadamente — sem URL pública, o acesso segue as permissões da app.)
  • UploadPublicFile — áudio para transcrição, ficheiros públicos quando necessário.
  • GenerateImage / GenerateVideo / GenerateSpeech — geração de conteúdos.
  • ExtractDataFromUploadedFile — extração estruturada de ficheiros.

04 — Frontend

Estrutura de pastas

src/
├─ App.jsx                 # Router (todas as rotas + auth providers + toasters)
├─ main.jsx                # Entry
├─ index.css              # Tokens de design + utilitários (gradientes, neon)
├─ api/base44Client.js     # SDK Base44 pré-inicializado
├─ lib/                    # lógica de apoio (utils, auth, rotas, config)
├─ hooks/                  # hooks reutilizáveis (useMySchool, useCurrentStudent, useCart...)
├─ components/
│  ├─ ui/                  # shadcn/ui (button, card, dialog, alert-dialog, select...)
│  ├─ shared/              # PortalSidebar, TopBar, NotificationDropdown, ThemeToggle...
│  ├─ landing/             # secções da landing page
│  ├─ announcements/       # feed, badges, diálogo de eliminar comunicado
│  ├─ finance/             # painel financeiro (login, provas, relatórios)
│  ├─ cafeteria/           # refeitório (refeições, stock, scanner QR)
│  ├─ national/            # gestão nacional (formulários de entidades, mapas)
│  ├─ feed/                # feed académico (post, reações, comentários)
│  ├─ studyRoom/           # salas de estudo
│  ├─ marketplace2/        # marketplace de parceiros
│  └─ ...                  # (profile, guardian, teacher, schedule, twisco, palavrasMinhas, events)
└─ pages/
   ├─ Landing.jsx  /auth/  /school/  /student/  /teacher/  /guardian/
   ├─ national/  /cafeteria/  /supplier/  /partner/  /marketplace/  /events/
   └─ *Dashboard.jsx        # layout de cada portal (sidebar + <Outlet/>)

Router (src/App.jsx)

Wrapper fixo: AuthProvider → QueryClientProvider → Router → ErrorBoundary → AuthenticatedApp + Toaster + FirstLoginPasswordNotice. Rotas autenticadas aninhadas em <ProtectedRoute>.

Rotas públicas

/ (Landing) · /relatorio-cae · /login · /forgot-password · /reset-password · /definir-senha · /primeiro-acesso · /auth-redirect · /bem-vindo · /cadastro/estudante · /cadastro/professor · /cadastro/encarregado · /financeiro

Rotas autenticadas (gerais)

/portal (seleção de portal) · /perfil · /validar-cartao/:code · /validar · /scanner · /sala/:token (entrar em sala de estudo por link)

Portal Nacional (/nacional/*)

index (Home) · escolas · refeitorio · estudantes · professores · encarregados · aprovacoes · relatorios · twisco · twisco/perfil · eventos (+criar/editar/estatisticas/detalhe) · fornecedor · parceiros · cartoes · cartoes/:id · carteiras · gestores · assinaturas · pagamentos · contabilidade · comunicados · notificacoes-automaticas

Portal Escola (/escola/*)

index · estudantes · encarregados · professores · turmas (+:id) · notas · frequencia · desempenho-docente · eventos (+detalhe/meu-calendario) · comunicados · reclamacoes · refeitorios · configuracoes · cartoes

Portal Estudante (/estudante/*)

index (feed académico) · salas (+:id) · palavras-minhas (+:id) · cartao · notas · frequencia · trabalhos · horario · mensagens · marketplace (+servico/:id) · reservas · favoritos · refeitorio (+:id) · carteira · ptt · planos · historico · avaliar-professores · cae-score · eventos (+detalhe/meu-calendario/twisco) · reclamacoes · comunicados

Portal Professor (/professor/*)

index · gerir-turma · avaliacoes · twisco · eventos · perfil · turmas (+:id) · notas · frequencia · comunicar · historico · marketplace · refeitorio · comunicados

Portal Encarregado (/encarregado/*)

index · filhos · educando/:id · notas · frequencia · trabalhos · mensagens · eventos · comunicados · carteira · cartoes

Portal Parceiro (/parceiro/*)

index · produtos · refeitorio · servicos · profissionais · reservas · pedidos · avaliacoes · comentarios · relatorios · financeiro · configuracoes · comunicados

Portal Refeitório (/refeitorio/*)

index · pedidos · refeicoes · escolas · stock · validar · fornecedor (+:id) · meu-refeitorio · fornecedor-pedidos · relatorios · pagamentos · comunicados

Portal Fornecedor (/fornecedor/*)

index · refeicoes (+:refeitorioId) · produtos · pedidos · classificacao · perfil · comunicados

* → PageNotFound

Padrões de página

  • Cada portal = *Dashboard.jsx (layout: PortalSidebar + TopBar + <Outlet/>) + páginas-filhas focadas.
  • Dados: useQuery/useMutation (TanStack Query); filtros/contagens/agregações no servidor (base44.entities.X.filter/count/aggregate). Páginas leem .items.
  • Notificações: NotificationDropdown + NotificationsModal filtram por portal ativo e por expires_at (24h).
  • Subscrições em tempo real: base44.entities.X.subscribe(event => ...) para listas que precisam de atualização ao vivo.
  • Componentização: ficheiros focados (≤50 linhas quando possível); páginas grandes são divididas em sub-componentes (ex.: AutoNotifications → StatsGrid, ScheduleTab, MessagesTab, HistoryTab).

Sistema de design

Tokens (src/index.css)

Definidos em :root (claro) e .dark (escuro, tom navy/slate sem neon). Mapeados em tailwind.config.js para classes (bg-primary, text-muted-foreground, font-heading...).

  • Cores semânticas: background, foreground, card, popover, primary (lilás 263 70% 58%), secondary (navy), muted, accent (laranja 24 92% 55%), destructive, border, input, ring.
  • Extensões CAE: energy, lilac, orange, navy, sky, pink, chart-1..5, sidebar.*.
  • Raio: --radius: 0.875rem.

Tipografia

  • Plataforma: Space Grotesk (--font-heading/body/display).
  • Landing page: Inter (via classe .font-landing, que sobrepõe os tokens de fonte localmente) — tom corporativo neutro.
  • Carregadas por @import no topo do index.css (antes de @tailwind base).

Gradientes e estética (utilitários em @layer utilities)

  • .bg-grad-primary (lilás→laranja), .bg-grad-cool, .bg-grad-warm, .bg-grad-pink, .bg-grad-blue, .bg-grad-lilac.
  • .text-grad-primary (texto com gradiente), .icon-grad-primary.
  • Landing (neon suave sobre branco): .neon-surface, .neon-surface-alt, .neon-glow, .neon-glow-strong, .neon-panel, .neon-panel-soft, .neon-chip, .neon-text, .neon-dot, .neon-hover, .neon-bottom, .neon-line.

Componentes base (src/components/ui/)

shadcn/ui: button (variantes default/destructive/outline/secondary/ghost/link; default usa .bg-grad-primary), card, dialog, alert-dialog, select, input, textarea, label, badge (variantes incl. lilac/orange/navy/sky), switch, checkbox, tabs, table, dropdown-menu, sheet, tooltip, calendar, scroll-area, etc.

Convenções visuais

  • Botão principal = gradiente lilás→laranja.
  • Cantos arredondados generosos (xl), sombras suaves (shadow-soft/card/pop).
  • Scrollbar discreta; dark mode limpo (sem brilhos).
  • Ícones: lucide-react (apenas ícones existentes/importados).

05 — Segurança e Fluxos

Autenticação

A plataforma gere a auth (tokens, sessões, OTP, reset, OAuth Google). A app adiciona:

  • Login padrão (/login): e-mail+senha, OAuth Google, OTP após registo, reset/forgot. Após login, completeAccountSetup liga a entidade e define user_type; resolveLoginIdentifier resolve username/telemóvel/e-mail.
  • Primeiro acesso (/primeiro-acesso): código de 6 dígitos (verifyAccessCode) → definir senha (setupAccountPassword).
  • Painel Financeiro (/financeiro): auth própria por username + senha (sem e-mail), validada em financeAuth (hash PBKDF2-SHA256 via createCredentials); emite session_token com session_expires_at. Sessão verificada backend-side em cada chamada.
  • Reset de senha padrão da plataforma; e-mails do sistema (reset, verificação, convite) usam a identidade visual da app.

Nota: a verificação de e-mail obrigatória ao nível da plataforma persiste comoKnown issue.

Papéis e permissões

| Papel | Acesso | | --- | --- | | admin | Tudo. Vê e gere todos os painéis nacionais, utilizadores e entidades. | | gestor | Gestor nacional. Secções visíveis definidas por national_permissions (src/lib/nationalPermissions.js); paridade operacional com admin nas ações de gestão (criar/editar/eliminar entidades, aprovar pagamentos, gerir comunicados/auto-notificações). | | user | Estudantes, professores, encarregados e contas de entidades. user_type direciona ao portal correto. |

As permissões por secção do painel nacional vivem em src/lib/nationalPermissions.js (metadados de secções + filtros por papel).

Row-Level Security (RLS)

Regras em base44/entities/<Nome>.jsonc → chave rls (ver guia RLS). Padrões usados no CAE:

  • Owner-or-admin: dono do registo (created_by_id == user.id ou data.user_id) ou role admin/gestor. Ex.: Notification, AutoNotificationPreference, RefectoryReview.
  • Admin/gestor-only (gestão): create/read/update/delete só admin/gestor. Ex.: AutoNotificationSettings, AutoNotificationMessage, AutoNotificationLog, FinanceAccount, AccountSetupToken.
  • Leitura aberta + escrita admin/gestor (conteúdo publicado): Announcement (read: {}, create: {}, update/delete: admin|gestor), SchoolConfig.
  • Aberto para criar, próprio/admin para ler: submissões de utilizadores (MealReview, RefectoryReview...).
  • Update condicional (fluxo de pagamentos): SubscriptionPayment e PTTTopupRequest só permitem update por admin/gestor quando finance_status ∈ {aprovado,rejeitado} — garante a ordem das duas fases.
  • Quase aberto (com delete restrito): Student (leitura/criação/update abertos para fluxos escolares; delete só admin/gestor). ScanLog (create próprio, read aberto, update/delete admin/gestor).
  • Entidades com null/{} mantêm-se abertas quando o dado é genuinamente partilhado (ex.: leitura de comunicados, catálogo público).

Recomendação contínua

Entidades novas devem trazer sempre rls — sem regra, o acesso é aberto a qualquer utilizador autenticado (e, em apps públicas, a anónimos). O dono dos dados define o padrão: dados pessoais → owner-or-admin; submissões de visitantes → create aberto + read próprio/admin; conteúdo publicado → read aberto + escrita admin/gestor.

Fluxo de pagamentos (duas fases)

Garante que Contabilidade/Finanças valida o comprovativo antes de Admin/Gestor aprovar. Lógica partilhada em base44/shared/paymentFlow.ts.

                    [Estudante/Encarregado submete comprovativo]
                                  │
            SubscriptionPayment / PTTTopupRequest criado
            status = pendente, finance_status = aguardando
                                  │
                       notifyPaymentPending ──► Admin/Gestor (in-app + e-mail)
                                  │
            ┌─────────────────────▼─────────────────────┐
            │  Painel Financeiro (financeAuth)          │
            │  Contabilidade valida o comprovativo:     │
            │   finance_status = aprovado | rejeitado    │
            │   (+ finance_observation se rejeitado)    │
            └─────────────────────┬─────────────────────┘
                                  │  (RLS: update só se finance_status já decidido)
            ┌─────────────────────▼─────────────────────┐
            │  Admin/Gestor (Nacional › Aprovações)     │
            │  status = aprovado | rejeitado            │
            │   • aprovado: subscription_start/end      │
            │            (carregamento: creditar PTT)   │
            │   • rejeitado: rejection_reason           │
            └──────────────────────────────────────────┘
  • Allowlist de e-mails: CAE_EMAIL_RECIPIENTS (notificationRecipients.ts) — só contas admin/gestor listadas recebem e-mails CAE (as restantes continuam a receber notificações in-app).
  • Anti-duplo-crédito: credited em PTTTopupRequest.
  • Auditoria: GestorActivity regista ações dos gestores; AutoNotificationLog regista envios.

Notificações automáticas (Bom dia / Palavras sábias / Boa noite)

Núcleo em base44/shared/autoNotifications.ts. Horários predefinidos: 08:00 / 12:00 / 20:00 (Luanda, janela de 6 min).

  1. Workflow Notificações Automáticas (cron 5 min) → runAutoNotifications.
  2. Lê AutoNotificationSettings (slots por categoria), AutoNotificationPreference por utilizador, e escolhe uma AutoNotificationMessage aprovada (rotação por last_used_at, evita repetições recentes).
  3. Personaliza {{nome}}/{{name}}, respeita canal (ambos/plataforma/e-mail), período de silêncio e horários pessoais.
  4. Entrega in-app (Notification com source=automatico, auto_category, expires_at = +24h) + e-mail (em lotes de 6) aos autorizados (canReceiveCaeEmail).
  5. Regista cada envio em AutoNotificationLog com dedupe_key (categoria+dia+utilizador) — impede duplicações.
  6. cleanupAutoNotifications remove as notificações automáticas que passaram das 24h.

Administração no painel Nacional › Notificações Automáticas (AutoNotifications.jsx): stats, agendamento, biblioteca de mensagens, histórico, envio de teste e geração por IA (opcional, ai_enabled).

Outros fluxos relevantes

  • Inscrição em eventos (registerForEvent): valida vagas, gera bilhete com qr_token/validation_code/ticket_code; para eventos pagos em Kz/PTT valida e debita ptt_balance do estudante; check-in via /scanner//validar (regista em ScanLog).
  • Cartão CAE: estados pendente → aprovado → impresso → pronto → entregue (ou reemitido/cancelado); mudança de card_status notifica encarregados. Validação por /validar-cartao/:code e leitura QR.
  • Feed académico: AcademicPost com visibility (minha_turma/minha_classe/meu_nivel/minha_escola) + reações educativas + comentários; moderação (status: ativo/denunciado/oculto).
  • Salas de estudo: delegado gere membros, materiais, tarefas, eventos; entrada por convite ou link partilhável (/sala/:token).
  • Eliminação de comunicado: Admin/Gestor elimina Announcement + remove as Notification distribuídas (AnnouncementDeleteDialog).

Itens abertos / dívida técnica

  • Concluir a auditoria para dar paridade total de gestor com admin.
  • Corrigir full_name de 16 encarregados existentes.
  • Refactorizar páginas com >400 linhas.
  • Substituir ~201 valores hexadecimais hardcoded por tokens do design system.
  • Integrar UnregisteredSchoolsList nos fluxos do dashboard nacional.
  • Verificação de e-mail obrigatória da plataforma persiste.

06 — Manual Operacional

Este manual descreve como se opera o CAE dia a dia, por domínio, e quem faz o quê. Para regras/constantes (preços, taxas, níveis, categorias) ver 07 — Regras e Configuração; para papéis e segurança ver 05 — Segurança.

1. Onboarding (adesão de entidades)

Todas as adesões seguem o padrão convite → código → senha → primeiro login.

| Entidade | Quem convida | Fluxo | | --- | --- | --- | | Escola | Admin/Gestor | provisionEntityAccount cria School + AccountSetupToken (código 6 dígitos, 24h) + e-mail. Escola abre /primeiro-acesso, insere o código (verifyAccessCode), define senha (setupAccountPassword). No 1.º login completeAccountSetup liga School.owner_user_id e user_type=escola. | | Refeitório | Admin/Gestor | Mesmo fluxo; entidade Refectory, user_type=parceiro. | | Fornecedor B2B | Admin/Gestor | Entidade CafeteriaSupplier, user_type=parceiro. | | Parceiro de serviços | Admin/Gestor | Entidade Partner, user_type=parceiro. | | Gestor nacional | Admin | Token entity_type=gestor; no 1.º login é promovido a role=gestor, user_type=nacional. | | Operador Financeiro | Admin/Gestor | Criado em FinanceAccount (username+senha, sem e-mail) via manageFinanceAccounts. |

Estudantes, professores e encarregados auto-registam-se em /cadastro/... (validação de telemóvel/BI/foto). O encarregado associa-se a estudantes existentes (vincula guardian_user_ids).

2. Subscrição, carteira PTT e cartão CAE

Teste gratuito

  • Todo o estudante novo tem 24h de teste gratuito (trial_start → trial_end = +24h).
  • Notificação por e-mail às 12h antes de expirar (processSubscriptions, trial_12h_notification_sent).
  • Expirado o teste, subscription_status = trial_expired e o acesso é bloqueado (checkStudentAccess).

Planos de assinatura (Kz)

| Plano | Preço | Duração | | --- | --- | --- | | Trimestral | 1.300 Kz | 3 meses | | Semestral | 2.500 Kz | 6 meses | | Anual | 3.500 Kz | 12 meses | | Cartão CAE (só cartão) | 3.500 Kz | — |

  • O estudante/encarregado escolhe o plano, paga e envia o comprovativo → SubscriptionPayment (status=pendente, finance_status=aguardando).
  • Cartão físico é opcional em qualquer plano (+3.500 Kz) ou comprado isoladamente (plano cartao).
  • Aprovação segue o fluxo de duas fases. Na aprovação, subscription_start/end são calculados por computeSubscriptionEnd.
  • A cada 15 min, processSubscriptions expira assinaturas vencidas.

Carteira PTT

  • Taxa oficial: 1 Kz = 0,85 PTT (configurável pelo admin em WalletConfig.ptt_rate_kz).
  • Presets de carregamento: 1.000 / 2.500 / 5.000 / 10.000 / 20.000 / 50.000 Kz. PTT mínimo após conversão: 10.
  • Carregamento = PTTTopupRequest (comprovativo + duas fases). Aprovado → credited=true e crédito em Student.ptt_balance (registado em PTTTransaction).
  • PTT gasta-se em: refeitório (encomendas), eventos pagos e (futuro) marketplace.

Cartão CAE — ciclo de vida

pendente → aprovado → impresso → pronto → entregue (ou reemitido / cancelado).

  • Mudança de card_status notifica automaticamente os encarregados (workflow).
  • Validação por /validar-cartao/:code e leitura QR (/scanner, /validar) → ScanLog.
  • Histórico em CardHistory.

3. Gestão académica (Escola)

  • Turmas (ClassRoom): criação/gestão pela escola; detalhe por turma com estudantes e professores.
  • Notas (Grade): lançadas pelo professor; notifica encarregados automaticamente.
  • Presenças (Attendance): registo pelo professor; notifica encarregados; alimenta o CAE Score (Assiduidade).
  • Trabalhos (Assignment + AssignmentSubmission): professor cria, estudante entrega, professor avalia; notifica encarregados.
  • Ocorrências (Occurrence) e Reclamações (Complaint): registo e seguimento.
  • Configuração escolar (SchoolConfig): classes, períodos, ano letivo, disciplinas, cursos — definidos pela escola.
  • Desempenho docente: rankings derivados de avaliações de professores (TeacherReview).

4. Feed académico (CAE Creator)

  • Estudantes publicam AcademicPost (resumo, exercício, vídeo, foto, projeto, experiência, trabalho, PDF, mapa mental, dica, flashcard, notícia).
  • Visibilidade escolhida: minha_turma / minha_classe / meu_nivel / minha_escola.
  • Reações educativas: Excelente, Muito Bom, Inteligente, Muito Útil, Boa Ideia, Criativo, Inspirador (contabilizadas, com teto anti-inflação).
  • Comentários (AcademicComment); moderação (status: ativo/denunciado/oculto); destaque (is_featured).

5. Salas de estudo e Palavras Minhas

  • Salas (StudyRoom): criadas por um delegado, por disciplina; membros, materiais, mensagens, tarefas, eventos. Entrada por convite ou link partilhável (/sala/:token) com limite e validade opcionais.
  • Palavras Minhas: ferramenta pessoal de estudo — calendário, sessões de estudo (pontuam no CAE Score se ≥25 min), tarefas/desafios, calculadora.

6. Eventos

  • Criação nacional (/nacional/eventos/criar) ou escolar, com categorias, organizador (escola/nacional/parceiro), target_roles, local, data, capacidade.
  • Pagamento: gratuito, kwanza, ptt ou combinado. Inscrição via registerForEvent — valida vagas, gera bilhete (qr_token, validation_code 6 dígitos, ticket_code CAE-XXXXXXXX) e, se pago em Kz/PTT, debita ptt_balance.
  • Check-in por QR (/scanner//validar) → EventRegistration.checked_in + ScanLog.
  • Publicação/cancelamento e inscrição notificam automaticamente os públicos-alvo (distributeEventNotifications).
  • Avaliação pós-evento (EventReview).

7. Refeitório (consumidor) e Fornecedores (B2B)

Refeitório

  • O operador gere refeições (Meal) por categoria (pequeno-almoço, almoço, lanche, jantar, aperitivos, bebidas) e produtos (revendidos; avaliação vai ao fornecedor).
  • Encomendas (Order) pagas em PTT, com estados: pendente → confirmado → em preparação → pronto a levantar → levantado (+ cancelado). Cada transição envia notificação ao estudante.
  • Stock (StockItem/StockMovement) por categoria; validação de pedidos por QR.
  • Avaliações MealReview (refeição ou produto) e RefectoryReview.

Fornecedores B2B

  • Catálogo (SupplierProduct/Product), encomendas de/para refeitórios (SupplierOrder/SupplyOrder), campanhas de abastecimento (SupplyCampaign), stock e despesas (CafeteriaExpense).
  • Avaliações de produto (ProductReview); perfis e ligações a refeitórios.

8. Marketplace & Parceiros

  • Parceiros oferecem serviços (Service) com variações e profissionais (Professional); reservas (Booking) com calendário.
  • Itens de marketplace (MarketplaceItem), encomendas (MarketOrder), carrinho (CartItem), favoritos (Favorite), avaliações (MarketplaceReview).

9. Twisco (concurso)

  • Concurso nacional com candidatos (TwiscoCandidate), votos (TwiscoVote) e configuração (TwiscoConfig) segundo critérios em twiscoCriteria.js. Presente nos portais Estudante, Professor e Nacional.

10. Comunicações

  • Comunicados nacionais (/nacional/comunicados): Admin/Gestor escolhe painéis-alvo (targets); distribuição automática in-app + e-mail; eliminação também remove as notificações enviadas.
  • Comunicados escolares (/escola/comunicados): escola envia a estudantes/professores/encarregados, opcionalmente por turma.
  • Notificações automáticas (Bom dia 08:00, Palavras sábias 12:00, Boa noite 20:00): validade 24h, preferências por utilizador, allowlist de e-mails.
  • Notificar encarregados: workflows acionados por nota/presença/trabalho/comunicado/PTT/mudança de cartão.
  • Cada portal vê só as notificações do seu portal (portal field).

11. Gestão nacional (CAE)

| Secção | Operação | | --- | --- | | Home | Indicadores globais. | | Escolas / Estudantes / Professores / Encarregados | Registos, detalhe, ações (eliminar estudante em cascata, etc.). | | Aprovações | Pagamentos (assinatura + carregamento PTT) — decisão final após Contabilidade. | | Cartões | Estado dos cartões CAE, impressão em lote, detalhe. | | Carteiras | Saldos PTT, transações. | | Gestores | Promover/despromover, permissões por secção. | | Contabilidade | Acessos e operação do painel Financeiro. | | Pagamentos | PaymentConfig (IBAN, valores). | | Fornecedor / Parceiros / Refeitório | Gestão de entidades B2B. | | Eventos | Criação/estatísticas. | | Comunicados / Notificações Automáticas | Comunicação central. | | Twisco | Gestão do concurso. |

07 — Regras e Configuração

Constantes e regras de negócio extraídas do código (src/lib/* e src/components/**/*Config.js). Editar nestes ficheiros para ajustar valores.

Subscrição e preços (subscriptionConfig.js)

| Chave | Valor | | --- | --- | | PLANS.trimestral | 1.300 Kz · 3 meses | | PLANS.semestral | 2.500 Kz · 6 meses | | PLANS.anual | 3.500 Kz · 12 meses | | CARD_PLAN.cartao | 3.500 Kz · só cartão (sem assinatura) | | PHYSICAL_CARD_PRICE | 3.500 Kz | | TRIAL_HOURS | 24 h | | CONTACT_PHONE | +244 923 730 122 |

computeSubscriptionEnd(planId, start) soma os meses; daysRemaining/trialRemainingMs/formatRemaining calculam tempo restante.

Carteira PTT (walletConversion.js)

| Chave | Valor | | --- | --- | | DEFAULT_PTT_RATE_KZ | 0,85 (1 Kz = 0,85 PTT) | | KZ_PRESETS | 1.000 / 2.500 / 5.000 / 10.000 / 20.000 / 50.000 Kz | | MIN_PTT | 10 PTT |

pttRate(config) usa WalletConfig.ptt_rate_kz se definido pelo admin, senão o padrão CAE. kzToPtt(kz, config) arredonda; minKz(config) é o Kz mínimo para atingir MIN_PTT.

CAE Score (caeScoreConfig.js / caeScoreEngine.js)

Níveis

| Nível | Nome | Pontos | | --- | --- | --- | | 1 | Iniciante | 0–99 | | 2 | Explorador | 100–249 | | 3 | Participante | 250–499 | | 4 | Destaque | 500–999 | | 5 | Mestre CAE | 1.000–1.999 | | 6 | Embaixador CAE | 2.000+ |

Marcos (recompensas em PTT)

100 → 10 PTT · 250 → 25 · 500 → 50 · 1.000 → 100 · 2.000 → 250.

Pontos por ação

Presença 10 · Bónus de sequência 15 · Trabalho entregue 15 (+5 se pontual) · Presença em evento 20 · Sessão de estudo 10 · Tarefa/desafio 5 · Post 12 (cap 20 posts) · Reação recebida (cap 40) · Comentário dado 3 (cap 40).

Categorias e tetos

Assiduidade 200 · Comportamento 100 · Trabalhos 200 · Participação 200 · Disciplina 100 · Estudo 200 · Comunidade 200 · Eventos 200.

Emblemas (10)

Aluno Exemplar, 30 Dias Sem Faltas, Melhor Média (≥16), Entregas em Dia, Participação Activa, Mestre da Matemática (≥18), Criador de Conteúdo (5+ posts), Ajudante CAE (10+ comentários), Leitor do Mês (20+ sessões), Espírito de Equipa (5+ comentários).

O motor computeCAEScore(raw) apenas computa (não persiste); combina presenças, notas, entregas, sessões, tarefas, posts, eventos e comentários, respeitando tetos e anti-inflação.

Eventos (eventConfig.jsx)

  • 20 categorias: Festival Escolar, Feira Científica, Workshop, Palestra, Concurso, Competição, Visita de Estudo, Feira de Emprego, Seminário, Académicos, Ciência e Tecnologia, Competições, Desporto, Cultura, Música, Carreira e Emprego, Empreendedorismo, Gaming/E-Sports, Festas, Comunidade.
  • Organizadores: escola, nacional (CAE), parceiro.
  • Pagamento: gratuito / kwanza / ptt / combinado.
  • Bilhete: genTicketCode → CAE-XXXXXXXX; genValidationCode → 6 dígitos; qr_token UUID.
  • target_roles (vazio ou todos = todos); isEventForRole filtra por portal.

Refeitório — refeições e produtos (mealConfig.js)

Refeições (6): Pequeno Almoço, Almoço, Lanche, Jantar, Aperitivos, Bebidas. Produtos (8, revenda): Bebidas, Laticínios, Padaria, Snacks, Hortofruto, Conservas, Higiene, Outros.

  • availability(meal): preparado = stock_available, vendido = stock_consumed, disponível = max(0, preparado−vendido).
  • fmtPtt(n) → N PTT (formato pt-PT).

Encomendas de refeitório (orderConfig.js)

Estados e notificação ao estudante em cada transição:

| Estado | Etiqueta | Notificação | | --- | --- | --- | | pendente | Pendente | — | | confirmado | Confirmado | "O teu pedido foi confirmado." | | em_processamento | Em preparação | "O teu pedido está a ser preparado." | | pronto_levantamento | Pronto a levantar | "Dirige-te ao refeitório." | | concluido | Levantado | "Bom apetite!" | | cancelado | Cancelado | "O teu pedido foi cancelado." |

statusFromOrder normaliza histórico (pedido_realizado→pendente).

Stock de refeitório (stockConfig.js)

Categorias: Grãos e Cereais, Leguminosas, Farináceos, (…) — cada uma com ícone/cor. Movimentos registados em StockMovement.

Reações educativas (feed)

Excelente · Muito Bom · Inteligente · Muito Útil · Boa Ideia · Criativo · Inspirador.

Visibilidade de posts (AcademicPost.visibility)

minha_turma · minha_classe · meu_nivel · minha_escola.

Notificações automáticas (autoNotifications.ts)

  • Horários: bom_dia 08:00 · palavras_sábias 12:00 · boa_noite 20:00 (janela 6 min).
  • TTL: 24 h. Lotes de e-mail: 6. Máx. tentativas: 3. Fuso: Africa/Luanda.
  • dedupe_key = categoria + dia + utilizador (impede duplicações).

Estados de referência

  • Cartão CAE (Student.card_status): pendente · aprovado · impresso · pronto · entregue · reemitido · cancelado.
  • Subscrição (Student.subscription_status): trial_active · trial_expired · payment_pending · payment_rejected · subscription_active · subscription_expired.
  • Pagamento (SubscriptionPayment/PTTTopupRequest): status pendente/aprovado/rejeitado + finance_status aguardando/aprovado/rejeitado.
  • Estudante (Student.status): pendente · activo · candidato · suspenso · graduado · desistente.

Tipos de notificação (Notification.type)

comunicado · nota · presenca · evento · marketplace · cartao · ptt · sistema · urgente · sala_estudo · pedido · fornecedor · stock · entrega · refeitorio · pagamento · mensagem.

Geografia

  • Províncias e municípios de Angola: src/lib/angolaRegions.js.
  • Indicativos telefónicos: src/lib/countries.js (seletor PhoneCountryPicker).
  • Telemóveis formatados xxx xxx xxx; validação de unicidade por checkPhoneExists.

Fusos e idioma

  • Fuso operativo: Africa/Luanda (UTC+1, sem horário de verão).
  • Interface e conteúdos: português de Angola.
  • Moedas: Kwanza (Kz) e PTT (carteira interna).

08 — Gestão, Responsabilidades e Operação

Matriz de responsabilidades (RACI)

Legenda: R responsável de executa · A aprova · C consultado · I informado.

| Atividade | Admin | Gestor | Escola | Financeiro | Estudante/Encarregado | Professor | | --- | --- | --- | --- | --- | --- | --- | | Convidar/promover gestores | A | C | — | — | — | — | | Aprovar acesso de entidades (escolas/refeitórios/fornecedores/parceiros) | A/R | R | I | — | — | — | | Registar/configurar escola | A | R | R | — | — | — | | Criar acessos do painel Financeiro | A | R | — | I | — | — | | Validar comprovativo (1.ª fase) | I | I | — | R | I | — | | Aprovar/rejeitar pagamento (2.ª fase) | A/R | R | — | C | I | — | | Emitir cartão CAE / estados | A | R | C | — | I | — | | Criar comunicado nacional | A/R | R | — | — | I | — | | Criar comunicado escolar | I | I | R | — | I | — | | Configurar notificações automáticas | A | R | — | — | I | — | | Criar evento nacional | A/R | R | C | — | I | C | | Inscrever em evento / pagar | — | — | — | — | R | R | | Lançar notas/presenças/trabalhos | I | I | C | — | I | R | | Gerir refeitório (refeições/stock) | I | I | — | — | — | — | | Gerir fornecedor (produtos/encomendas) | I | I | — | — | — | — | | Publicar no feed / salas de estudo | — | — | — | — | R | R | | Eliminar estudante (cascata) | A/R | R | C | — | — | — | | Eliminar comunicado | A/R | R | — | — | — | — |

Gestor tem paridade operacional com Admin nas ações de gestão; secções visíveis no painel nacional dependem de national_permissions.

Operações automáticas (workflows)

| Cadência/Evento | O que faz | | --- | --- | | A cada 5 min | Envia notificações automáticas do horário + remove as expiradas (>24h). | | A cada 15 min | processSubscriptions: expira testes (24h), notifica 12h antes, expira assinaturas. | | Announcement create | Distribui comunicado nacional (in-app + e-mail). | | Announcement create | Notifica encarregados (comunicado escolar). | | Grade/Attendance/Assignment/PTTTransaction create | Notifica encarregados. | | Student update (card_status) | Notifica encarregados (estado do cartão). | | EventRegistration create | Notifica inscrição em evento. | | Event update (status) | Notifica publicação/cancelamento de evento. |

Publicação e ambientes

  • App publicada em https://cae-smart-campus.base44.app; domínio próprio caeao.com (estado da verificação a acompanhar no dashboard).
  • Build: npm run build (Vite). Sem segredos no código; segredos em set_secrets (atualmente google_oauth_client_secret).
  • Funções backend servidas em /functions/<nome>; invocadas pelo SDK dentro da app.
  • E-mails do sistema (reset, verificação, convite) usam a identidade visual CAE; e-mails de negócio (comunicados, validação de contabilidade, pagamentos, auto-notificações) usam templates MJML em base44/emails/.

Erros conhecidos e troubleshooting

| Sintoma | Causa/Ação | | --- | --- | | Informação no verso do cartão de identidade truncada | Bug de layout do componente de BI — ajustar dimensões. | | Domínio caeao.com "pending" | Verificação no dashboard (Domínios) — DNS/CNAME. | | Pedidos de registo de professor não aparecem no portal da escola | Verificar Teacher.school_id e enrollment_status. | | Estudantes sem escola/encarregado associado | Corrigir registos; lista de não-registados no dashboard nacional. | | 16 encarregados com full_name incorreto | Correção manual pendente. | | E-mails não chegam a admin/gestor | Verificar CAE_EMAIL_RECIPIENTS (allowlist) em notificationRecipients.ts. | | Notificação duplicada de auto-msg | dedupe_key (categoria+dia+utilizador) deve impedir; verificar AutoNotificationLog. | | Pagamento não avança | Confirmar finance_status decidido pela Contabilidade antes de o Admin/Gestor aprovar. | | Verificação de e-mail obrigatória persiste | Restrição da plataforma — Known issue. |

Dívida técnica (aberto)

  • Concluir paridade gestor ↔ admin.
  • Refactorizar páginas com >400 linhas.
  • Substituir ~201 valores hexadecimais hardcoded por tokens do design system.
  • Integrar UnregisteredSchoolsList nos fluxos do dashboard nacional.
  • Eliminar catch {} silenciosos (8+) que mascaram erros.
  • Rever inconsistências de dados em Meals/Orders, Eventos e marketplace.

Manutenção recorrente recomendada

  • Diária: revisar aprovações pendentes, comunicados e notificações automáticas (dashboard nacional).
  • Semanal: auditoria de GestorActivity, relatórios financeiros, estados de cartões.
  • Mensal: revisão de AutoNotificationLog (entregues/parciais/falhou), saldo de créditos de integração, relatórios B2B.
  • Por ano letivo: configurar SchoolConfig (classes, períodos, ano letivo, disciplinas, cursos).

Contacto e convenções

  • Telefone CAE: +244 923 730 122 (formato xxx xxx xxx).
  • Toda a comunicação interna/documentação em português de Angola.
  • Valores monetários em Kz; carteira interna em PTT (1 Kz = 0,85 PTT salvo configuração do admin).