Multi-Partner Funding, Event Sourcing, and Real-Time Financial Management
This digital project tracking system provides comprehensive management for multi-partner funded projects with sophisticated financial controls, real-time monitoring, and compliance enforcement.
Track every dollar from commitment through disbursement with automated validation, balance tracking, and reconciliation. The system enforces funding source rules, prevents over-commitment, and maintains a complete financial audit trail.
Manage multiple funding partners with different contribution levels, disbursement rules, and reporting requirements. Each partner's funds are tracked independently while maintaining project-level visibility.
Generate detailed reports for stakeholders, auditors, and regulators. The event-sourced architecture provides complete transparency and supports point-in-time reconstruction of any account state.
Every state change is captured as an immutable event. Events are never deleted or modified, only appended. Current state is derived by replaying the event stream.
project_created - New project initializationfunding_committed - Partner commits fundsdisbursement_requested - Request for fund releasedisbursement_approved - Approval granteddisbursement_executed - Funds transferredmilestone_completed - Project milestone achievedThe rules engine validates every transaction against configurable business rules. Rules are defined declaratively and can be updated without code changes.
| Category | Purpose | Example |
|---|---|---|
| Validation | Ensure data integrity | Amount must be positive |
| Authorization | Check permissions | Requires two approvers |
| Limits | Enforce constraints | Max 20% per disbursement |
Every financial transaction creates two entries: a debit and a credit. This ensures the books always balance and provides built-in error detection.
// Example: $10,000 disbursement
Debit: Project Expenses +$10,000
Credit: Funding Pool -$10,000
Net Balance Change: $0
{
"project_id": "string (UUID)",
"name": "string",
"description": "string",
"status": "enum [planning, active, completed, suspended]",
"start_date": "ISO 8601 date",
"end_date": "ISO 8601 date",
"total_budget": "decimal",
"funding_partners": [
{
"partner_id": "string (UUID)",
"partner_name": "string",
"committed_amount": "decimal",
"disbursed_amount": "decimal",
"rules": {
"max_single_disbursement": "decimal",
"requires_milestone": "boolean",
"approval_threshold": "integer"
}
}
],
"milestones": [
{
"milestone_id": "string (UUID)",
"name": "string",
"target_date": "ISO 8601 date",
"status": "enum [pending, completed, missed]",
"funding_release": "decimal"
}
],
"created_at": "ISO 8601 timestamp",
"updated_at": "ISO 8601 timestamp"
}
{
"event_id": "string (UUID)",
"event_type": "string",
"aggregate_id": "string (UUID)",
"aggregate_type": "enum [project, disbursement, partner]",
"timestamp": "ISO 8601 timestamp",
"user_id": "string (UUID)",
"payload": {
// Event-specific data
},
"metadata": {
"ip_address": "string",
"user_agent": "string",
"correlation_id": "string (UUID)"
},
"sequence_number": "integer"
}
{
"disbursement_id": "string (UUID)",
"project_id": "string (UUID)",
"amount": "decimal",
"currency": "string (ISO 4217)",
"status": "enum [requested, approved, rejected, executed, failed]",
"requested_by": "string (UUID)",
"requested_at": "ISO 8601 timestamp",
"approved_by": ["string (UUID)"],
"approved_at": "ISO 8601 timestamp",
"executed_at": "ISO 8601 timestamp",
"funding_sources": [
{
"partner_id": "string (UUID)",
"amount": "decimal",
"percentage": "decimal"
}
],
"purpose": "string",
"category": "enum [labor, materials, equipment, services, other]",
"milestone_id": "string (UUID, optional)",
"supporting_documents": ["string (URL)"],
"validation_results": {
"rules_passed": ["string"],
"rules_failed": ["string"],
"warnings": ["string"]
}
}
{
"entry_id": "string (UUID)",
"transaction_id": "string (UUID)",
"account": "string",
"type": "enum [debit, credit]",
"amount": "decimal",
"currency": "string (ISO 4217)",
"balance_before": "decimal",
"balance_after": "decimal",
"timestamp": "ISO 8601 timestamp",
"description": "string",
"reference_type": "enum [disbursement, commitment, refund, adjustment]",
"reference_id": "string (UUID)"
}
{
"rule_id": "string (UUID)",
"name": "string",
"description": "string",
"category": "enum [validation, authorization, limit, timing]",
"priority": "integer (1-100)",
"enabled": "boolean",
"conditions": [
{
"field": "string (JSONPath)",
"operator": "enum [eq, ne, gt, gte, lt, lte, in, contains]",
"value": "any",
"logical_operator": "enum [AND, OR]"
}
],
"action": "enum [allow, deny, require_approval, warn]",
"message": "string",
"applies_to": ["enum [all, partner_specific]"],
"partner_ids": ["string (UUID)"]
}
{
"rule_id": "rule_001",
"name": "Max Single Disbursement 20%",
"description": "No single disbursement can exceed 20% of total project budget",
"category": "limit",
"priority": 90,
"enabled": true,
"conditions": [
{
"field": "$.amount",
"operator": "gt",
"value": "$.project.total_budget * 0.20"
}
],
"action": "deny",
"message": "Disbursement exceeds 20% of total project budget",
"applies_to": ["all"]
}
{
"rule_id": "rule_002",
"name": "Milestone Required for Large Disbursements",
"description": "Disbursements over $50,000 require completed milestone",
"category": "authorization",
"priority": 85,
"enabled": true,
"conditions": [
{
"field": "$.amount",
"operator": "gt",
"value": 50000,
"logical_operator": "AND"
},
{
"field": "$.milestone_id",
"operator": "eq",
"value": null
}
],
"action": "deny",
"message": "Disbursements over $50,000 require an associated completed milestone",
"applies_to": ["all"]
}
{
"rule_id": "rule_003",
"name": "Dual Approval Required",
"description": "Disbursements require approval from two authorized users",
"category": "authorization",
"priority": 95,
"enabled": true,
"conditions": [
{
"field": "$.approved_by.length",
"operator": "lt",
"value": 2
}
],
"action": "deny",
"message": "Disbursement requires approval from at least two authorized users",
"applies_to": ["all"]
}
CREATE TABLE events (
event_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
event_type VARCHAR(100) NOT NULL,
aggregate_id UUID NOT NULL,
aggregate_type VARCHAR(50) NOT NULL,
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
user_id UUID NOT NULL,
payload JSONB NOT NULL,
metadata JSONB,
sequence_number BIGSERIAL,
INDEX idx_aggregate (aggregate_id, sequence_number),
INDEX idx_event_type (event_type),
INDEX idx_timestamp (timestamp)
);
CREATE TABLE projects (
project_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
description TEXT,
status VARCHAR(50) NOT NULL,
start_date DATE NOT NULL,
end_date DATE,
total_budget DECIMAL(15,2) NOT NULL,
total_committed DECIMAL(15,2) DEFAULT 0,
total_disbursed DECIMAL(15,2) DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CHECK (total_budget >= 0),
CHECK (total_disbursed <= total_committed)
);
CREATE TABLE funding_partners (
partner_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(project_id),
partner_name VARCHAR(255) NOT NULL,
committed_amount DECIMAL(15,2) NOT NULL,
disbursed_amount DECIMAL(15,2) DEFAULT 0,
rules JSONB,
CHECK (committed_amount >= 0),
CHECK (disbursed_amount <= committed_amount)
);
CREATE TABLE disbursements (
disbursement_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(project_id),
amount DECIMAL(15,2) NOT NULL,
currency CHAR(3) DEFAULT 'USD',
status VARCHAR(50) NOT NULL,
requested_by UUID NOT NULL,
requested_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
approved_by UUID[],
approved_at TIMESTAMPTZ,
executed_at TIMESTAMPTZ,
purpose TEXT NOT NULL,
category VARCHAR(50) NOT NULL,
milestone_id UUID,
validation_results JSONB,
CHECK (amount > 0)
);
CREATE TABLE ledger_entries (
entry_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
transaction_id UUID NOT NULL,
account VARCHAR(100) NOT NULL,
entry_type VARCHAR(10) NOT NULL CHECK (entry_type IN ('debit', 'credit')),
amount DECIMAL(15,2) NOT NULL CHECK (amount >= 0),
currency CHAR(3) DEFAULT 'USD',
balance_before DECIMAL(15,2) NOT NULL,
balance_after DECIMAL(15,2) NOT NULL,
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
description TEXT,
reference_type VARCHAR(50) NOT NULL,
reference_id UUID NOT NULL,
INDEX idx_account (account, timestamp),
INDEX idx_transaction (transaction_id)
);
CREATE TABLE rules (
rule_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
description TEXT,
category VARCHAR(50) NOT NULL,
priority INTEGER NOT NULL CHECK (priority BETWEEN 1 AND 100),
enabled BOOLEAN DEFAULT true,
conditions JSONB NOT NULL,
action VARCHAR(50) NOT NULL,
message TEXT,
applies_to VARCHAR(50)[] NOT NULL,
partner_ids UUID[],
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Test the rules engine with different disbursement scenarios. Enter values below and click "Validate" to see which rules pass or fail.