Overview
The RAF Admin Console is a staff-facing Django app (InviteFriendConsole) bundled with the Banno integration. FI staff sign in with a Django user account (is_staff=True) and manage campaigns, review individual referrals, and pay or record reward payouts.
The console is mounted at /console/ on the same service that hosts the member plugin. Authentication is Django’s standard session login — there is no Banno OIDC on the admin side.
| Route | Purpose |
|---|---|
GET /console/ | Per-FI overview: counts + active campaigns |
GET /console/referrals/ | Filterable referral list + bulk actions |
GET /console/referrals/<id>/ | Referral detail with eligibility JSON |
POST /console/referrals/<id>/pay/ | Mark inviter/acceptor reward as paid |
GET /console/campaigns/new/ | New campaign form |
POST /console/campaigns/<id>/toggle/ | Activate / deactivate a campaign |
GET /console/campaigns/<id>/edit/ | Edit dates and switches on an existing campaign |
1. Overview Dashboard

| Tile | Derived from |
|---|---|
| Total Referrals | Referral.count() |
| Submitted | Referral.filter(status='submitted').count() |
| Criteria Met | Referral.filter(status='criteria_met').count() |
| Ready to Pay | Referral.filter(status='ready_to_pay').count() |
| Paid | Referral.filter(status='paid').count() |
| Expired | Referral.filter(status='expired').count() |
| Members | Member.count() (all members with an RAF record, not only those who submitted or referred) |
NewRelationshipCampaign / NewProductCampaign), optional restriction User ID, priority, start/end dates, and both reward amounts.
- Edit — opens the edit modal for that campaign.
- Status toggle — fires
POST /console/campaigns/<id>/toggle/. A green toggle indicates the campaign is active and currently within its date window. Toggling off effectively ends the campaign immediately. - Add New Campaign — opens the new-campaign form described below.
priority is the one surfaced first in the inviter tile. During submission itself, a referral row is created for every matching active campaign regardless of priority.
2. Referrals List

| Filter | Notes |
|---|---|
| From Date / To Date | Bounds on submitted_at. Defaults to the last 7 days. |
| Transaction Status | Maps to Referral.status (submitted, criteria_met, ready_to_pay, paid, expired, all). |
| Campaign | Drop-down of this tenant’s campaigns. |
| Column | Source |
|---|---|
| Pay Reward / Mark as Paid | Row-level checkbox for bulk actions |
| Ready to Reward? | Yes when status='ready_to_pay', else No |
| Campaign | Referral.campaign.name |
| Inviter Name | Member.first_name + last_name of the inviter |
| Inviter Reward Host Account ID | Referral.inviter_primary_account_id — snapshotted at submission time from the inviter’s Banno accounts, resolved via campaign.inviter_rda_codes |
| Inviter Amount | campaign.inviter_amount captured on the referral |
| Acceptor Name / Host Account ID / Amount | Same fields for the acceptor |
| Button | Behavior |
|---|---|
| Pay Reward | Triggers the configured payment provider (auto mode) for the selected rows — transfers funds to the snapshotted host account IDs and moves the referral to paid. |
| Mark as Paid | For mark_external mode — records the payout as completed without triggering a transfer. Use when the FI runs payouts outside the system. |
| Download | Exports the current filter result as CSV — the same report scheduled monthly to the FI’s configured recipient list. |
inviter_rda_codes narrows it to a different product code.
3. New Campaign Form

Campaign.
Top-level fields
| Field | Column | Notes |
|---|---|---|
| Name | name | Human-readable campaign name |
| Campaign Type | campaign_type | NewRelationshipCampaign or NewProductCampaign |
| Creator User ID | creator_user_id | Optional — restricts code generation to a specific member (used for ambassador / influencer campaigns). Leave blank for open campaigns. |
| Start Date / End Date | start_date, end_date | Inclusive bounds; the status toggle is only effective within this window |
| Inviter Amount | inviter_amount | USD reward paid to the inviter; set to $0.00 for promo/acceptor-only campaigns |
| Acceptor Amount | acceptor_amount | USD reward paid to the acceptor |
| CCW Days | ccw_days | Criteria Completion Window — days from submission for the acceptor to satisfy all criteria |
| Payment Mode | payment_mode | auto, manual, or mark_external |
| Max Inviter Rewards | max_inviter_rewards | Checkbox + count. Checked = capped; unchecked = unlimited |
| Inviter RDA Type | inviter_rda_codes | JSON array of product codes used to resolve the inviter’s destination account (e.g., ["checking"]) |
| Acceptor RDA Type | acceptor_rda_codes | Same for acceptor (e.g., ["savings"]) |
| Do Not Pay Codes | do_not_pay_codes | JSON array of influencer codes — if the acceptor uses one of these, the inviter reward is suppressed for attribution |
| Priority | priority | Higher = shown first if multiple campaigns match |
| Promo Code | promo_code | Optional FI self-promotion code — acceptor-only reward, is_promo=true on the referral |
Payment Mode semantics
| Mode | Behavior |
|---|---|
auto | On transition to ready_to_pay, the backend automatically calls the payment provider and moves the referral to paid. |
manual | Referral waits in ready_to_pay until a staff user clicks Pay Reward in the list view. |
mark_external | Referral waits in ready_to_pay; staff click Mark as Paid to record an off-system payout. No transfer is attempted. |
Criteria Config builder
| Criterion | Config field | Input |
|---|---|---|
| Account | criteria_config.account | Account type string (default Checking) |
| Balance | criteria_config.balance.min_balance | Minimum acceptor balance during the CCW window |
| Payroll | criteria_config.payroll.min_amount | Cumulative direct-deposit threshold (default 500) |
| Debit | criteria_config.debit.min_count | Minimum qualifying debit transaction count (default 5) |
account AND balance AND (payroll OR debit)) stored on criteria_config.logic. Each checkbox enables that criterion; unchecked criteria are ignored by the engine regardless of logic.
Submit
On Submit the form posts toPOST /console/campaigns/. The server validates:
start_date <= end_date.- At least one criterion is enabled if the type is
NewProductCampaign. promo_codeis unique across active campaigns for this tenant.do_not_pay_codesis valid JSON.
