Overview
National data · Real time
Distribuição por Província
Staff por Parceiro × Tipo
🏘️ OCBs por Província
| Província | OCBs | Grants Activos | Total Financiado |
|---|---|---|---|
| — | |||
⚠️ Contratos a Expirar (90 dias)
| Nome | Província | Fim | Dias |
|---|---|---|---|
| — | |||
Staff por Função (Top 10)
🏘️ Por OCB / Parceiro
| Parceiro | Staff Total | Activos | Massa Sal. MZN | Sal. Médio |
|---|---|---|---|---|
| — | ||||
🗺 Por Província (Staff)
| Província | Total | Activos | Massa Sal. MZN |
|---|---|---|---|
| — | |||
Lista de Trabalhadores
| Nome | Parceiro | Província | Função | Tipo | Status | Fim Contrato | Salário |
|---|---|---|---|---|---|---|---|
Staff / Workers
Unified register with PEPFAR HRH
| Nome ↕ | Parceiro ↕ | Província ↕ | Função ↕ | Cadre HRH | Status | Financiador | Início ↕ | Contract | Salário ↕ | Acções | |
|---|---|---|---|---|---|---|---|---|---|---|---|
Partner OCBs
Community-Based Organisations
| OCB | Localização | Tipo | Staff | Massa Sal. MZN | Grants | Execução | Saldo/Total | Contacto | Acções |
|---|---|---|---|---|---|---|---|---|---|
Subcontracted
Staff subcontracted via CBE, Nweti and other organisations
| # | Nome | Organização | Posição / Colocação | Província | Início | Fim | Sal. Base | CBE Fee 9% | Sal. Líquido | Status | Acções | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
Grants Management
All PEPFAR grants — per OCB lifecycle view
Disbursements
Record of all payments received by grant and OCB
| Date | OCB | Grant | Tranche | Amount | Currency | Payment Ref. | Notes |
|---|---|---|---|---|---|---|---|
Contract Modifications
All grant modifications across all OCBs — ceiling changes, obligated adjustments, overspending alerts
HRH Reports & Analysis
Operational indicators, PEPFAR and trends
Workforce Planning
Current headcount by role × province — set targets and view gaps
Import Data
Select the data type and upload an Excel or CSV file
Audit Log
Record of all system actions · Click a row to view change details
| Data/Hora | Utilizador | Acção | Colecção | Documento | Província | Alterações |
|---|---|---|---|---|---|---|
| Carregue os logs de auditoria | ||||||
Settings
System administration
Adicionar Utilizador Firebase
Utilizadores Registados
| Nome | Perfil | Âmbito | Activo | Último Acesso | Acções | |
|---|---|---|---|---|---|---|
Adicionar Província
Províncias e Distritos
Adicionar Cadre HRH
| Cadre | Interaction Type | Acções |
|---|
🔐 Firestore Security Rules — complete ruleset
Copy and paste the entire block below into Firebase Console → Firestore → Rules. Replace everything.
allow read: if isAuth(); on the users collection —
required so that getRole() can resolve correctly when evaluating write permissions on grants, OCBs, etc.
Without this, all writes fail with permission-denied even for admins.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isAuth() { return request.auth != null; }
// getRole() reads the user's own profile — works correctly because
// users allow read: if isAuth() (any authenticated user can read profiles)
function getRole() {
return isAuth()
? get(/databases/$(database)/documents/users/$(request.auth.uid)).data.get('role', '')
: '';
}
function canWrite() {
return isAuth() && getRole() in ['admin','gestor_nacional','gestor_provincial'];
}
function canWriteSubcontr() {
return isAuth() && getRole() in ['admin','gestor_nacional','gestor_provincial','gestor_subcontr'];
}
function isOwner() {
return isAuth() && request.auth.uid == resource.data.authorId;
}
// ── Users ──
// allow read: if isAuth() is intentional — getRole() needs to read any user profile
// to evaluate write permissions across all other collections.
match /users/{uid} {
allow read: if isAuth();
allow create: if isAuth();
allow update: if isAuth() && (request.auth.uid == uid || getRole() == 'admin');
allow delete: if isAuth() && getRole() == 'admin';
allow list: if isAuth() && getRole() in ['admin','gestor_nacional'];
}
// ── Workers / Staff ──
match /workers/{wid} {
allow read: if isAuth();
allow create, update: if canWrite();
allow delete: if isAuth() && getRole() in ['admin','gestor_nacional'];
match /history/{hid} { allow read: if isAuth(); allow write: if canWrite(); }
match /comments/{cid} {
allow read, create: if isAuth();
allow update: if isAuth() && (isOwner() || getRole() in ['admin','gestor_nacional']);
allow delete: if isAuth() && (isOwner() || getRole() in ['admin','gestor_nacional']);
}
}
// ── OCBs and all grant sub-collections ──
match /ocbs/{oid} {
allow read: if isAuth();
allow create, update: if canWrite();
allow delete: if isAuth() && getRole() in ['admin','gestor_nacional'];
match /comments/{cid} {
allow read, create: if isAuth();
allow update, delete: if isAuth() && (isOwner() || getRole() in ['admin','gestor_nacional']);
}
match /grants/{gid} {
allow read: if isAuth();
allow write: if canWrite();
match /desembolsos/{did} { allow read: if isAuth(); allow write: if canWrite(); }
match /historico/{hid} { allow read: if isAuth(); allow write: if canWrite(); }
match /modificacoes/{mid} { allow read: if isAuth(); allow write: if canWrite(); }
match /inkind_items/{iid} { allow read: if isAuth(); allow write: if canWrite(); }
match /despesas/{did2} { allow read: if isAuth(); allow write: if canWrite(); }
match /comments/{cid} {
allow read, create: if isAuth();
allow update, delete: if isAuth() && (isOwner() || getRole() in ['admin','gestor_nacional']);
}
}
}
// ── Subcontracted ──
match /subcontratados/{doc} {
allow read: if isAuth();
allow create, update: if canWriteSubcontr();
allow delete: if isAuth() && getRole() in ['admin','gestor_nacional'];
match /notas/{nid} {
allow read: if isAuth();
allow create: if canWriteSubcontr();
allow delete: if isAuth() && (isOwner() || getRole() in ['admin','gestor_nacional']);
allow update: if false;
}
match /historico/{hid} { allow read: if isAuth(); allow write: if canWriteSubcontr(); }
match /comments/{cid} {
allow read, create: if isAuth();
allow update, delete: if isAuth() && (isOwner() || getRole() in ['admin','gestor_nacional']);
}
}
// ── Team feed ──
match /team_feed/{doc} {
allow read, create: if isAuth();
}
// ── App config ──
match /config/{doc} {
allow read: if isAuth();
allow write: if isAuth() && getRole() == 'admin';
}
// ── Audit log ──
match /audit_logs/{doc} {
allow read: if isAuth() && getRole() in ['admin','gestor_nacional'];
allow create: if isAuth();
allow update, delete: if false;
}
// ── Notification queue (Cloud Function processes these) ──
match /notification_queue/{doc} {
allow read: if isAuth() && getRole() in ['admin','gestor_nacional'];
allow create: if isAuth();
allow update, delete: if false;
}
match /user_notifications/{uid}/items/{id} {
allow read, write: if isAuth() && request.auth.uid == uid;
}
// ── Email queue (fila_email — Cloud Function trigger) ──
match /fila_email/{doc} {
allow read: if isAuth();
allow create: if isAuth();
allow update, delete: if false;
}
// ── Presence ──
match /presence/{uid} {
allow read: if isAuth();
allow write: if isAuth() && request.auth.uid == uid;
}
// ── Chat ──
match /chat_messages/{channel}/messages/{mid} {
allow read, create: if isAuth();
allow delete: if isAuth() && (isOwner() || getRole() in ['admin','gestor_nacional']);
allow update: if false;
}
match /chat_messages/{channel}/typing/{uid} {
allow read: if isAuth();
allow write: if isAuth() && request.auth.uid == uid;
}
// ── Procurement contracts ──
match /contratos_procurement/{cid} {
allow read: if isAuth();
allow write: if isAuth() && getRole() in ['admin','gestor_nacional','procurement','operacoes'];
match /adendas/{aid} { allow read: if isAuth(); allow write: if isAuth() && getRole() in ['admin','gestor_nacional','procurement','operacoes']; }
match /historico/{hid} { allow read: if isAuth(); allow write: if isAuth() && getRole() in ['admin','gestor_nacional','procurement','operacoes']; }
}
// ── Deny everything else ──
match /{document=**} {
allow read, write: if false;
}
}
}
📋 PEPFAR HRH Inventory Export
Gera o ficheiro Excel no formato PEPFAR HRH Inventory (FY25) pronto para submissão no DATIM. Inclui 4 sheets: Cover, HRH_Inventory, Summary_by_Cadre, Summary_by_Province.
Data Maintenance
Data cleaning, validation and repair tools
Qualidade dos Dados
🤝 Subcontracted — Corrigir Organização
organizacao preenchido não aparecem para o Gestor de Subcontratos.
Esta ferramenta estampa a organização em todos os registos que não têm este campo.
🧹 Limpeza de Campos
🔎 Duplicados & Validação
📊 Score de Completude por Parceiro / OCB
⚠️ Detecção de Anomalias Salariais
🗓️ Revisão Periódica de Dados
Rastreio de quando cada parceiro/OCB confirmou pela última vez que os seus dados estão actualizados. Recomendado a cada 90 dias.
🇺🇸 Conformidade PEPFAR/DATIM
Resultados
📥 Grants Staging — Ligar Registos a Grants
Registos do Excel sem grant criado ficam aqui em staging. Clique ⚡ Auto-ligar Todos depois de criar os grants — os registos com Grant No. identificado são ligados automaticamente.
⚠️ Zona de Perigo
Acções irreversíveis. Faça export antes de prosseguir.