HC

Project 05 / 08

BC Cancer Foundation CRM

Donor Engagement Platform

Donor management CRM for the BC Cancer Foundation. Weighted multi-criteria matching across interests, geography, donation history, recency, and capacity, with explainable breakdowns. Full RBAC and immutable audit trail.

01

What it does

A donor engagement and event management CRM built for the BC Cancer Foundation industry capstone. Fundraisers can run their donor directory, create and track events, score which donors match an event invitation, and review a full audit trail of every administrative action.

02

Matching pipeline

Each donor and event pairing scores against six weighted factors. Weights are configurable per event type so a small in-person gala can prioritise different signals than a broad mail campaign:

FactorSignal
Interest alignmentOverlap between donor causes and event theme
Geographic proximityPostal code radius
Donation historyTotal contributions and channel mix
RecencyMonths since last contribution
Engagement levelEmail, event attendance, response rate
CapacityGiving tier signal

The ranked donor list comes back with a per-factor breakdown rather than just a final score, so a fundraiser can see exactly why a donor ranked where they did and adjust weights with intuition rather than guesswork.

03

Schema and access patterns

TypeORM models map cleanly to a normalised relational schema (User, Donor, Event, EventDonor, AuditLog) without N+1 fetches. Indexes target the four hottest access patterns: donor lookup by ID, event roster, donations by donor over a time window, and matches by event.

Local development uses SQLite for fast boots. Production deploys against PostgreSQL or MySQL via TypeORM connection options, so the schema is portable across both engines.

04

Role-based access control

Three roles enforced consistently across the stack:

  • Admin covers the full administrative surface including audit-log access
  • Manager can mutate events and donors, no audit-log access
  • Staff get read-only directory and analytics

NestJS guards run on every controller. The frontend also gates routes by role so users do not see UI for actions they cannot perform.

05

Audit trail

Every administrative mutation writes to audit_logs with:

  • Actor user ID and role
  • Entity type and entity ID
  • Action verb
  • Before and after state as JSONB diffs
  • Sanitised request payload (PII redacted)
  • IP address and timestamp

The log is queryable through the admin API with filters by date range, actor, action, or entity type. CSV and JSON exports drop straight into compliance reporting.

GET /admin/audit-logs?action=donor.update
  &entityType=Donor
  &startDate=2025-01-01
  &endDate=2025-12-31
  &page=1&limit=50

06

Analytics

Dashboard endpoints surface donor segmentation, geographic distribution, gift velocity, and engagement channel mix. The same queries that power the dashboards are exposed at /analytics/* so the data is reusable in scheduled exports or downstream tools.

07

Stack

LayerStack
FrontendReact 18, Vite, Tailwind, shadcn/ui
BackendNestJS, TypeScript, TypeORM
DatabasePostgreSQL (production), SQLite (local)
AuthSession cookies, NestJS guards
API docsSwagger at /api/docs

Seeder populates 500 donors, sample events, and audit history on first boot so the app is browsable immediately after npm start. CI runs the backend and frontend test suites on every push via GitHub Actions.