My Projects
No projects yet
Create your first project to get started
Dashboard
-
-
-
Income
Revenue by Client
| Project | Client | Phase | Spent | Contract | Consumed |
|---|
| Project | Client | Total Amount | Client Status | Contract Status | Bonus % | Contributors | Bonus Amount | |
|---|---|---|---|---|---|---|---|---|
| Total | ||||||||
Management Staff Bonus
| Role | Name | Condition (M-1) | Value (M-1) | Status | Bonus |
|---|---|---|---|---|---|
| Total Management Bonus | |||||
Recap per Person
| Name | Contract Type | Total Bonus | Action |
|---|
| Date | Bank Account | Third | Category | Wording | Amount | |
|---|---|---|---|---|---|---|
| Total | ||||||
| Category | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec | Total |
|---|
Clients
No clients yet
Add your first client to get started
Team Members
Manage your global team directory. Members can then be assigned to projects with specific roles.
No team members yet
Projects
No projects for this client
Description
Quality Check
| Name | Contract | Signed FA | Rate | CV | Passport | Bank | Phone | Nationality | Valid | Active TO |
|---|
Team
Contracts
Task Orders
Leave Management
Résumé des paiements
Missing payment account
Salaires
| Nom | Entité | Compte | Montant | Notes | Actions |
|---|---|---|---|---|---|
| Total | |||||
Payment Requests
| Consultant | Entity | Period | Amount | Status | Actions |
|---|---|---|---|---|---|
| Total | |||||
Expense Reports
| Reference | Consultant | Entity | Title | Period | Total TTC | Status | Submitted | Actions |
|---|
Notifications
Pay Parameters
Salary grid parameters used to calculate target annual salary. Formula: (Base × Experience + Seniority + Responsibility) × Setup × Workload
Budget Codes
Settings
Database Backup & Restore
Download a backup of the database or restore from a previous backup file.
Backup
Download a snapshot of the current database. Use this to transfer data between environments or as a safety backup.
Restore
Upload a .db backup file to replace the current database. A safety backup is created automatically before restoring.
Drag & drop a .db file here, or click to browse
Scheduled Backups (S3)
Daily at 2:00 AM Paris time — retained for 60 days
| File | Date | Size |
|---|
No backups found in S3
Loading backups...
Restore Database
You are about to replace the current database with:
This action will overwrite all current data. A backup of the current database will be saved automatically before restoring.
Login Logs
Track user login activity with IP and location.
| Date | User | IP Address | Location |
|---|
No login logs yet
Accountants
Configure accountant email addresses for notifications. Separate multiple addresses with ;
Test Portals
Generate test access links to preview the different portals. Links expire after 7 days.
Loading...
Architecture
Where data is stored and how the system is structured.
Server (Docker)
Flask + Gunicorn running in Docker on port 8003.
What's on the server:
- SQLite database —
data/portal.db(WAL mode) - All structured data: projects, clients, invoices, contracts, consultants, team members, portal tokens, audit logs
- JSON columns for nested data (budget, deliverables, line items, etc.)
Backed up automatically to S3 every day at 2 AM (Paris) + manual download via Settings → Database
AWS S3
Bucket ra-customer-portal-data in eu-west-1.
What's in S3:
- Documents — invoices (PDF), contracts (PDF/DOCX), signed documents
- Generated files — AI-generated reports, exported spreadsheets
- Signatures — consultant signature images (PNG)
- DB backups — daily automated backups under
backups/prefix (60-day retention)
Authentication
- Admin users — Firebase Auth (Google SSO) for @reliefapplications.org, @oortcloud.tech, @ouirace.com
- Consultant portals — magic links via portal tokens (no password)
- Client portals — magic links via portal tokens (no password)
Firebase users are managed outside the app — not in the DB backup
External Services
- AWS SES — sending emails (magic links, notifications)
- Mistral AI — content generation, document analysis
- Anthropic (Claude) — AI-assisted features
Stateless — no data stored externally
Domains & URLs
Single app serving multiple domains via Host header detection.
- dashboard.humanitarian.tech — Admin dashboard (all entities)
- portal.reliefapplications.org — RA consultant portal
- portal.oortcloud.tech — Oort consultant portal
- portal.ouirace.com — OuiRace consultant portal
All domains proxy to the same Docker container on port 8003 via nginx
In short
Core Business
projects
Core entityEach project belongs to a client and has phases, deliverables, time entries, and budget tracking.
id TEXT PK
name, slug (unique), status
client_id → clients
project_type deliverable | time_material
budget_eur, days_contract, days_spent
start_date, end_date
JSON columns:
budget, phases, deliverables
contacts, time_entries, invoice_ids
consumption_types, monthly_consumption
clients
Core entityOrganizations that own projects. One client can have many projects.
id TEXT PK
name, slug
contact_name, contact_email
sector, country
active INTEGER (bool)
notes
invoices
Core entityClient invoices with amounts, line items, and linked documents in S3.
id TEXT PK
invoice_number, title, client_name
amount, amount_ht, tva, ttc
currency, status
issue_date, due_date, year
tracking_code, document_key
JSON: line_items, tags
contracts
Core entityClient-facing contracts with value, dates, and linked PDF/DOCX in S3.
id TEXT PK
title, client_name, contract_type
value, currency
start_date, end_date
document_key
JSON: key_obligations, tags
consultants
Person recordPeople who work on projects. Each consultant can have multiple staff_contracts and task_orders.
id TEXT PK
full_name, email (unique)
position, nationality, country
phone, address
bank_name, bank_iban, bank_bic
password_hash, is_active
cv_document_key, passport_document_key
portal_tokens
AuthMagic-link tokens for client portal access. One token per project + email.
token TEXT PK
project_id → projects
email, expires_at, last_accessed
HR Module
staff_contracts
HRFramework agreements between the company and a consultant. Links to a consultants person record.
id TEXT PK
contract_id, name, position
consultant_id → consultants
contract_type, legal_entity
daily_rate, hourly_rate, currency
start_date, end_date, status
framework_signed, onboarding_complete
annual_salary, pagas, seguro
task_orders
HRSpecific work assignments under a staff contract. Tracks hours, deadlines, and signatures.
id TEXT PK
task_order_id, consultant_name
staff_contract_id → staff_contracts
project_id → projects
total_hours, hours_used, hours_remaining
rate, total_days, currency
status, to_status
consultant_signed, company_signed
payment_requests
HRConsultant payment submissions with invoice/timesheet documents. Goes through approval workflow.
id TEXT PK
staff_contract_id → staff_contracts
consultant_name, legal_entity
period_start, period_end, period_label
extracted_amount, validated_amount
status in_progress | validated | approved | rejected
Related: payment_request_lines, payment_request_logs, payment_supporting_documents
leave_records
HRVacation, sick leave, overtime, and primes for consultants.
id TEXT PK
staff_contract_id → staff_contracts
legal_entity, leave_type
date_start, date_end, day_type
status pending | approved | rejected
budget_codes
HRBudget line codes used to allocate task orders and payment lines to specific budgets.
id TEXT PK
code (unique), label
budget_eur, active
Supporting & System
project_bonuses
Monthly bonus percentages per project+phase. Contributors stored as JSON.
bonus_validations
Tracks which months have been validated (locked) for bonus distribution.
audit_logs
Login events, IP addresses, geolocation. Used in Settings → Logs.
hr_settings
Key-value store for HR config (accountant emails, CC addresses).
salary_history
Tracks salary changes over time for each staff contract.
signed_document_uploads
Uploaded signed versions of generated FA/TO documents.
monthly_export_log
Records of monthly payroll exports sent to accountants.
todos
Internal task tracking with priority, status, and entity (RA/OuiRace).
Key Relationships
clients 1 — N projects (via client_id)
consultants 1 — N staff_contracts (via consultant_id)
staff_contracts 1 — N task_orders (via staff_contract_id)
staff_contracts 1 — N payment_requests (via staff_contract_id)
staff_contracts 1 — N leave_records (via staff_contract_id)
payment_requests 1 — N payment_request_lines (via payment_request_id)
payment_requests 1 — N payment_request_logs (via payment_request_id)
projects 1 — N portal_tokens (via project_id)
projects 1 — N project_bonuses (via project_id)
Note: JSON columns (phases, deliverables, time_entries, contacts) are stored inside the projects table, not as separate tables.
Automated Daily Backup
A scheduled job runs every day at 2:00 AM Paris time. It creates a consistent DB snapshot and uploads it to S3.
S3 location: s3://ra-customer-portal-data/backups/portal_backup_YYYYMMDD_HHMMSS.db
Retention: 60 days — older backups are automatically deleted after each run
Can also be triggered manually from Settings → Database → "Backup Now"
Manual Download
Downloads a snapshot directly to your browser. Uses SQLite's native backup API — safe during active use.
What's included: all structured data (projects, clients, invoices, contracts, HR data, etc.)
What's NOT included: files in S3 (PDFs, signatures), Firebase user accounts
Restore
Upload a .db file (from manual download or S3 backup) to replace the current database.
1. Dry run — validates the file, compares row counts, flags resurrected records
2. Actual restore — creates a safety backup (portal.db.bak), replaces the DB, runs schema migration, re-applies deletions
Safety nets
- 60 days of daily backups in S3 — recover from any point in the last 2 months
- Automatic
portal.db.bakcreated before every restore - Integrity + schema validation before any overwrite
- Dry run to preview changes without risk
- Resurrection guard: previously deleted records are re-deleted automatically
My TODOs
TO Management
How Task Orders work in the portal.
Request a TO
Project Managers can request a new Task Order for a consultant directly from the portal. Here's how it works:
- Navigate to HR → Task Orders and click Request TO
- Select the consultant from the team list. Only consultants with an active contract can be assigned a TO.
- Fill in the details:
- Project — the project this TO is linked to
- Budget code — for financial tracking
- Start & deadline dates
- Total hours or days allocated
- Rate — daily or hourly rate for the consultant
- Description — scope of the work
- Submit the request. The TO is created with status draft.
After the request
- Generate the TO document — click to generate the PDF.
- Send for signature — click to email the TO to the consultant. They receive a magic link to review and sign.
- Consultant signs — the consultant opens the link, reviews the TO, and signs electronically. Status moves to Ongoing.
TO lifecycle
Consultant Invoice
How consultants submit invoices through the portal.
Submitting an invoice
Consultants submit invoices via the Consultant Portal. Each invoice is tied to a Task Order and a specific month.
- Open the portal — the consultant accesses their portal via the magic link sent by email.
- Select the Task Order — choose the active TO for which they want to submit an invoice.
- Fill in the payment request:
- Month — the period covered by the invoice
- Amount — the invoiced amount (based on days/hours worked × rate)
- Invoice PDF — upload the invoice document
- Timesheet — upload the signed timesheet for the period
- Submit — both the invoice and timesheet must be uploaded and the amount confirmed before submission is allowed.
What happens next
- Review — the PM and admin team are notified. They review the invoice and timesheet in the admin portal under HR → Payments.
- Approval — the payment request is validated and processed for payment.
- Payment — once paid, the status is updated and the consultant can see it in their portal.
Payment request lifecycle
Important notes
- Invoices must match the rate and conditions defined in the Task Order.
- A signed timesheet is mandatory for each payment request.
- Consultants can only submit invoices for Task Orders with status Ongoing.
- If a payment request needs correction, the admin can reject it and the consultant will be notified to resubmit.