Operator's Manual

Brotherhood Fishing Trip Dashboard

The complete guide to signups, dues, treasury, communications, and recruiting — for the trip coordinator and treasurer.
Version 2026 · Written for the flight from Norfolk

Contents

  1. Introduction — what this system does and why
  2. Authentication and roles
  3. The Fishing tab — the signup roster
  4. The Trip Status tab — who's paid, who's short
  5. Manual payments — cash, Venmo, Cash App, checks
  6. The Reconciliation tab — bank statements to categories
  7. The Treasury tab — Bank Balance vs Cash on Hand vs Net Brotherhood
  8. The Trip Expenses tab — receipts and reimbursements
  9. The Members / Dues tab — core-member roster
  10. The Recruiting tab — prospects, sponsors, pipeline
  11. The Communications tab — emails, SMS, templates
  12. The trainee notification system
  13. The System Map — self-documenting diagram tab
  14. Business rules and invariants
  15. Data model — where everything lives
  16. Troubleshooting and recovery
  17. Glossary

1Introduction — what this system does and why

The Brotherhood Fishing Trip Dashboard is a single-page web application that manages every moving part of the annual Brotherhood fishing trip: who signed up, who has paid, where the money is right now, who's recruiting whom, and how to reach the whole roster in one click. It replaces a folder of spreadsheets, a Zelle statement, a group text, and a mental Post-It note with one screen you can open from any phone or laptop.

The system has three audiences:

Why single-page Everything lives in one HTML file plus a set of Cloudflare Functions. There's no build step, no framework, no bundler. If something breaks on a plane you can open the file locally, hit save, and it works. The trade-off is that the file is large — read this manual before assuming a feature doesn't exist; it probably does, just hidden behind a role gate.

How data flows, at a glance

When a trainee signs up, Jotform posts a webhook to /api/jotform-webhook. The webhook writes a row into fishing_signups, matches the trainee against the prospects list (by email or phone), and auto-fills the sponsor if there's a match. That's the moment the signup appears on your Fishing tab and on the Trip Status cards.

When the trainee pays via Zelle, the money hits your bank account. You export a CSV from Truist, paste it into the Reconciliation tab, and split each transaction across categories — most commonly fishing_trip credited to a specific signup. The credit shows up as a green bar on the Trip Status card, and the signup's balance drops toward zero.

When the trainee pays cash, Venmo, Cash App, or a check, none of that touches the bank yet. You use the 💰 Record payment button on their Trip Status card to log a manual payment. That instantly credits their account and adds to the Cash on Hand tile on the Treasury tab. When you eventually deposit the cash to the bank, you reconcile the resulting bank credit as Cash Deposit — linking the deposit back to the specific manual payments it represents, so no dollar gets counted twice.

The mental model Every dollar the Brotherhood receives lives in one of three places: Bank Balance (in the bank), Cash on Hand (in your pocket / Venmo balance / etc), or has already been Spent (trip expenses). The three sum to Net Brotherhood. When someone hands you money, it changes location but does not become "new" money — that framing is what keeps the treasury math honest across every workflow.

What this system deliberately does NOT do

2Authentication and roles

The dashboard is locked behind Supabase Auth. There is no anonymous access; every page load requires a signed-in user. Sign-in works two ways:

Google OAuth (admins)

Anyone with a Google account can click Sign in with Google on the login screen. On first sign-in they land in the system as a pending user with no dashboard access — just a message that says an admin will review the request. A super_user promotes them to user, manager, or super_user from the Users management panel.

Email magic link (members)

Members whose email is already on the roster can request a magic-link sign-in without going through Google. Type email, click Send magic link, click the link in the resulting email, land signed in. This exists specifically for members who don't want to associate a Google identity with the Brotherhood.

The role hierarchy

RoleWhat they can do
pending Nothing. They see a "your access is pending approval" screen. No tabs are accessible.
user Read-only access to Fishing, Trip Status, Communications templates, Recruiting (scoped to their own prospects). Cannot reconcile, cannot see Treasury or Trip Expenses. Intended for core members.
manager Everything user can do PLUS: reconcile bank transactions, send communications, edit any prospect, archive signups, edit sponsor assignments. Intended for the trip coordinator and assistant coordinators.
super_user Everything manager can do PLUS: Treasury tab (Bank Balance, Cash on Hand, Net Brotherhood, carryover), Trip Expenses tab, manual payments (Record Payment button), Cash Ledger, user role management. Intended for the treasurer.
Rule of thumb If a tab or button is missing when you're viewing on a member's account, that's the role gate hiding it. Sign in with your own super_user account to confirm the feature exists but is intentionally hidden from the lower role.

Who gets which role

Do not delete the bootstrap super_user If you remove or demote pvme2013@gmail.com and lose the password to every other super_user account at the same time, you will need database access to recover admin. Keep at least two active super_users on file.

3The Fishing tab — the signup roster

The Fishing tab is the list of everyone who has signed up for the current fishing trip. It's the most-used tab during the recruitment window and the source of every other roster in the system.

What each row shows

What you can do on this tab

  1. Archive a signup. Someone dropped out, got moved to next year, or the entry was a duplicate. Archive them so they don't clutter the roster but their history stays. Archived signups appear on Treasury as excluded from "expected" — see chapter 7.
  2. Bulk archive / restore. Select the checkboxes on multiple rows and use the sticky bulk bar at the bottom.
  3. See the full transaction history for a person. Click on the row. A modal opens showing every bank transaction that has been allocated to this person, with dates, descriptions, and the exact portion of each transaction that credited their trip account.

Why the Paid checkbox is read-only

Design decision There used to be a click-to-mark-paid workflow. It was disabled because manual "paid" flags without reconciled bank credits would drift from the treasury numbers. Now the Paid column derives from allocations: either you reconciled a bank credit or you recorded a manual payment, and both flow into the same math. If you see a green Paid checkmark but the treasury doesn't reflect the money, there's a legacy manual flag from before the freeze — reconcile the missing money to clear the discrepancy.

4The Trip Status tab — who's paid, who's short

Trip Status is the payment-focused view of the same roster. Where the Fishing tab is a table, Trip Status is a grid of cards — one card per active signup, colored by payment progress:

The pay-card, element by element

Each card is packed with information; here's what every piece means:

ElementMeaning
Name (with ⭐)Signup's full name. A star means they're also a core Brotherhood member (their name appears on the dues roster).
Sponsor chipWhich core member recruited this trainee. Tap the chip to reassign. Amber "⚠ Unassigned" means we don't know who brought them in.
EmailContact address on file. Used for payment confirmation emails.
Progress barPercentage paid, capped at 100%.
Amounts rowLeft: dollar amount reconciled. Right: balance still owed (or $0 if paid).
Status pill"Not paid" / "N% paid" / "✓ GOOD TO GO" / "✓ PAID +$X OVER".
💰 Record paymentSuper_user only. Opens the manual payment modal — see chapter 5.

Setting a sponsor

Sponsors get set two ways: automatically at signup time (if the trainee's email or phone matches a prospect on the Recruiting tab), or manually by tapping the sponsor chip on the card. The picker lists every active core member plus a special Core option for group-recruited trainees (people who showed up because of a general announcement, not a specific brother's outreach).

Sponsor assignments do not affect payment math. They exist purely for the recruiting scoreboard on the Recruiting tab, which credits each core member for the people they brought in.

Overages and what to do about them

If someone accidentally pays more than $175 — a duplicate Zelle, a mis-typed cash amount — the card turns orange and shows the amount over. Your options:

  1. Refund the trainee the excess and remove the extra allocation on the Reconciliation tab.
  2. Reassign the excess to other_income on the same bank transaction so it stops crediting the trip.
  3. Roll it forward as a partial payment toward next year — currently manual, not automated.
Refunds via manual payment If you refund a trainee $50 in cash from your pocket, you have effectively received a negative payment. There's no "refund" button in v1 — record it as a delete of the original manual payment (if applicable) or leave a note in the allocation on the Reconciliation tab. Either way, mark it clearly so future-you knows what happened.

5Manual payments — cash, Venmo, Cash App, checks

This chapter covers the most-used treasurer workflow: recording money that arrives outside the bank. It combines what the dashboard calls the "manual payment ledger" with the deposit-linking flow. The two together form a complete, no-double-count model of cash-in-hand.

The core insight

Why this is not "new income" When Bob hands you $175 cash, the Brotherhood is not $175 richer — Bob is $175 poorer and you are $175 heavier in the wallet. The same is true for a Venmo transfer sitting in your personal Venmo balance, a Cash App payment, or an uncashed check. It's a change of custody: money moves from Bob's pocket to your pocket to the bank. The dashboard models this literally: your pocket is called Cash on Hand, the bank is called Bank Balance, and the sum is called Net Brotherhood.

Recording a payment

  1. Open the trainee's Trip Status card and tap the amber 💰 Record payment button below the status pill. This button is visible to super_user only.
  2. Amount defaults to their remaining balance. Adjust if they paid a different amount.
  3. Method — Cash, Venmo, Cash App, Zelle (external / not yet in bank), Check, or Other. Pick what they actually handed you.
  4. Date received defaults to today. Backdate if you're recording a payment that came in yesterday.
  5. Notes — optional but recommended. Write the Venmo handle, memo line, check number, or context ("handed to me at Bible study, John will double-check").
  6. Email trainee confirmation — default on. Uncheck only if you're standing with the person and they don't need a redundant email.
  7. Save. The card refreshes, their balance drops, and (unless you opted out) a confirmation email lands in their inbox within seconds.

What just happened in the database

The system created one row in brotherhood_bank_allocations with these properties:

Because signups.js already sums fishing_trip allocations without filtering on transaction_id, the payment immediately counts toward the trainee's paid balance. No separate calculation, no parallel table.

Depositing cash to the bank — closing the loop

Eventually you take the cash to the bank. The next time you import your bank statement, that deposit will show up as a credit — say a $525 credit for the three brothers whose cash you deposited together. Here's how to reconcile it without double-counting:

  1. Import the bank statement as usual (Reconciliation tab → paste CSV).
  2. Find the deposit and expand it.
  3. Category dropdown → 💵 Cash deposit (link manual payments).
  4. An amber panel appears with a checklist of every undeposited manual payment. Tick the ones this deposit covers.
  5. The allocation amount auto-fills from the sum of checked rows. It should match the deposit; if it doesn't, you either missed a checkbox or the person paid a different amount than recorded.
  6. Save.

What just happened, part two

The cash_deposit allocation was created with category = 'cash_deposit' and the amount matching the bank credit. Behind the scenes, each linked manual payment's deposit_transaction_id got PATCH'd to the bank txn's id. Two important consequences:

No double count is possible Whether you reconcile a bank credit as fishing_trip (the traditional way, for Zelle payments) or as cash_deposit (for cash you already recorded manually), only one path contributes to the trainee's paid balance. You cannot accidentally double-count if you use the correct category — and if you use the wrong category, the treasury discrepancies panel will flag the overage.

Undoing a mistake

Every step in this flow is reversible:

The Cash Ledger panel

On the Treasury tab, expand 💵 Cash on hand — manual payment ledger. This shows every undeposited manual payment with date, trainee name, method, amount, notes, and a Delete button. There's also a "Show already-deposited payments" toggle that reveals historically deposited rows with a green ✓ badge — useful for audit or year-end reporting.

6The Reconciliation tab — bank statements to categories

Reconciliation is where you tell the system what each bank transaction was for. Every Zelle deposit that shows up on your Truist statement needs a category (usually fishing_trip, credited to a specific signup) and every fee, transfer, or purchase needs to be labeled too.

Importing a statement

  1. Log into Truist, open the account activity view, filter to the date range you haven't imported yet, and export to CSV.
  2. On the Reconciliation tab, paste the CSV contents into the import box. The parser handles Truist's default column order automatically; other formats work as long as they include date, description, amount, and balance columns.
  3. Click Import. Duplicate detection is based on (date, description, amount, balance), so re-importing the same statement is safe.

Allocating a transaction

Each transaction expands into an editor with these controls:

Categories, exhaustively

CategoryMeaningRequires
fishing_tripCredit toward a trainee's $175 trip cost.signup_id
dues_annualFull-year dues payment ($120) — spreads across 12 months in dues_payments.member_id, fiscal_year
dues_monthlyPartial dues, one month at a time.member_id, fiscal_year, month
rental_incomeIncome from something the Brotherhood rents out (e.g., trailer, equipment).
bank_interestInterest paid by Truist. Usually a few cents.
account_transferInternal moves between accounts (e.g., savings to checking).
outgoing_paymentGeneral outgoing payment that isn't a trip expense.
other_incomeAnything credit-side that doesn't fit above.
other_expenseAnything debit-side that doesn't fit above.
cash_depositA bank credit that deposits already-recorded manual payments. Requires linking specific manual payment rows.manual_payment_ids (checklist)

Overage prevention

Before a save, the system checks whether the new allocation would put anyone over the cap:

If it would, you get a confirm dialog listing exactly who would go over and by how much. You can proceed anyway (someone actually paid too much and you want to record it as an overage) or cancel and adjust.

The discrepancies panel

At the top of the Reconciliation tab is a panel that surfaces issues automatically:

Errors sort first, then warnings, then info. Click a row to drill into the person's transaction history.

The "Notify trainees on save" toggle

Above the transactions list is a global toggle that controls whether trainee notifications fire when a save changes their fishing_trip contribution. Default on. Turn it off for bulk imports or backfills where you don't want to spam the whole roster.

Copy from previous

When you allocate a new deposit from someone who has paid before, a hint appears above the allocation editor: "Use same allocations as [previous date]". Click it and the previous split gets applied to this transaction. Saves clicks when a member pays the same amount monthly.

7The Treasury tab — Bank Balance vs Cash on Hand vs Net Brotherhood

Treasury is the treasurer's one-screen dashboard for "how are we doing." Every number here derives from other tabs; nothing is entered here except the carryover figure.

The four top tiles

TileQuestion it answersFormula
Carryover from 2025 How much did we bring into the new year? Editable, stored in brotherhood_config.
Bank Balance How much is in the checking account right now? Latest balance column from the most recent bank txn.
Cash on Hand How much do we have that hasn't been deposited? Sum of undeposited manual payments.
Net Brotherhood What are our total assets, everywhere they live? Carryover + all reconciled income − trip expenses.
The relationship In a perfectly reconciled world with no undeposited cash, Net Brotherhood ≈ Bank Balance. Add manual payments and it becomes Net Brotherhood = Bank Balance + Cash on Hand. Any remaining gap after that is the known $40.41 historical discrepancy in your books, which is intentionally not chased.

Fishing Trip 2026 section

Dues + Other Income

Editing the carryover

Expand the ⚙️ Edit carryover panel to change the "brought into 2026" figure. Default is $1,324.76 per your books. Bank-actual carryover was $1,284.35 — the $40.41 gap is acknowledged and intentionally not reconciled to a specific transaction.

The Cash on Hand ledger

Expand the panel below the tiles to see every manual payment currently sitting in your custody, plus a toggle to reveal already-deposited history. See chapter 5 for the full flow.

8The Trip Expenses tab — receipts and reimbursements

Trip Expenses tracks money going OUT for the fishing trip: food, fuel, gear, lodging. It's separate from general Brotherhood expenses because the fishing trip has an internal budget the group cares about.

Logging an expense

  1. Tap Log expense on the top-right of the Trip Expenses tab.
  2. Enter vendor, date, amount, category (food, fuel, gear, lodging, etc), and any notes.
  3. Check the Reimbursable box if a member paid out-of-pocket and needs reimbursement. Uncheck if the Brotherhood account paid directly.
  4. Save.

Snap-a-receipt

The 📸 Snap Receipt button on mobile opens the camera. Take a picture of the receipt; the image gets uploaded to Supabase Storage, and the expense form pre-populates with what the vision model reads from the image (vendor, total, date). Verify the extracted fields, adjust if needed, save.

Marking reimbursements

When a reimbursable expense gets paid back, check the Reimbursed box on the row. The "reimbursable outstanding" total on the Treasury tab drops accordingly. This is a cross-check for the treasurer to make sure everyone got paid back before year-end.

Access

Trip Expenses is super_user only. Members don't see it. This is intentional — expense records include payment details and reimbursement status that aren't broadly relevant.

9The Members / Dues tab — core-member roster

The Dues tab tracks the annual $120 obligation for every core Brotherhood member. It's a fiscal-year grid: rows are members, columns are the 12 months (March through February), cells are green if paid, red if unpaid.

The core-member roster is fixed

Unlike signups, which come and go every year, the core member roster is deliberately closed. There is no "Add member" button and no "Paste from Excel" import on this tab. The eight core members are:

To add or remove a core member you edit brotherhood_dues_members directly in Supabase, then re-sync from the Dues tab. This friction is intentional — changing the core roster is a governance decision, not a click.

How a dues payment flows

When a member pays their dues, the money hits Truist via Zelle. You reconcile that transaction on the Reconciliation tab as dues_annual credited to the member for the appropriate fiscal year. The system spreads the $120 across all 12 months of that fiscal year (March through February) and flips all 12 cells green.

Partial dues payments use dues_monthly with a specific month picked. Useful for members catching up mid-year.

Contact information

Each row has a ✎ pencil icon to edit the member's email and phone. This information is used for the Communications tab (email nudges) and the SMS launcher.

Passcode

Access to the Dues tab is gated by the treasurer passcode. Core members bypass the passcode automatically because they need to see their own dues history. Everyone else needs to enter it.

10The Recruiting tab — prospects, sponsors, pipeline

Recruiting is the pre-signup pipeline. It answers the question: "who might sign up, and whose responsibility is that person?"

Adding a prospect

  1. Tap Add prospect at the top of the tab.
  2. Enter name, email or phone (at least one), notes, and the sponsor (which core member is following up with them).
  3. Save. The prospect appears on their sponsor's rollup and in the "All active prospects" filter on the Communications tab.

Prospect states

StatusWhat it means
newAdded but not yet contacted.
invitedNudged at least once. Auto-set the first time you email or SMS them.
signed_upThey filled out the Jotform. Auto-set by the webhook when the email/phone matches.
declinedThey told you no. Set manually.
archivedRemoved from the roll-up but preserved for history.

The rollup

The top of the Recruiting tab shows a scoreboard: each core member with their prospect count and status breakdown. The top scorer gets a gold border. This gives the group friendly accountability without shaming anyone.

The 📱 Log contact button

Each prospect card has a 📱 Log contact button. Tap it after you texted or called the person outside the dashboard (i.e., you didn't use the SMS launcher). It bumps invited_count and stamps last_invited_at to now, so the pipeline reflects that you actually reached out. Includes an ↶ Undo last button if you tapped by mistake.

Sponsor auto-fill on signup

When a prospect fills out the Jotform, the webhook matches their email or phone against the prospects table. On a match, the resulting signup's sponsor_name gets auto-populated from the prospect's sponsor. The prospect's status flips to signed_up and their signed_up_submission_id gets stamped.

Permission scope

Regular user-role core members see only prospects they own (sponsor_name matches their name) or created. Manager+ sees all prospects. This lets core members manage their own outreach without seeing everyone else's list.

11The Communications tab — emails, SMS, templates

Communications is the outbound-message hub. From here you can email the whole roster, text a single prospect, send a personalized nudge to every core member, or copy-paste a message to yourself for reference.

The compose flow

  1. Pick a recipient filter. Options: All signed up, Unpaid, Partial, Fully paid, Dashboard users, Custom emails, Single (one signup), All active prospects, Single prospect, Single core member, All core members.
  2. Optionally load a template. Templates live in brotherhood_communication_templates and can be edited or created inline.
  3. Edit the subject and body. Use personalization tokens: {first}, {name}, {last}, {email}, {paid}, {balance}, {trip_cost}, and (for core-member sends) {prospects_list}, {prospects_count}, {new_prospects_count}, {invited_prospects_count}, {signed_up_prospects_count}.
  4. Preview recipients. Expand the "Preview recipients (N)" section to see who exactly will get the message.
  5. Preview as first recipient. Shows how the tokens expand for the first person in the list — sanity check before you fire off 30 emails with a typo.
  6. Send. Confirms with a sample of names before firing. Every send is logged in brotherhood_communications.

Email vs SMS channel toggle

At the top of the compose panel, switch between Email and SMS. Email sends through Gmail SMTP via the brotherhood-send-comm edge function. SMS opens iOS Messages one recipient at a time — you tap Send in Messages manually.

The SMS launcher

When Channel = SMS, a new panel appears below the send row:

Tapping a row does three things simultaneously: syncs-copies the personalized text to the clipboard, opens iOS Messages with the recipient's number, and fires the auto-log call for prospects.

Why the clipboard fallback exists

iOS pre-fill is unreliable Modern iOS increasingly strips the body parameter from sms: URLs when they contain URLs, newlines, or certain characters. The dashboard uses the RFC-standard sms:PHONE?body=TEXT format, which works most of the time. When iOS drops the body, the clipboard fallback saves the day — the personalized text is already copied, so you long-press the Messages text field and hit Paste.

The Nudge template

A specific template ships in the system for keeping recruiters on track. Filter = "All core members", template = "Nudge — Your recruiting pipeline". Each core member gets ONE email listing only THEIR active prospects with contact info and status. No one sees anyone else's list. Send this weekly during the recruitment window and pipelines will not go stale.

12The trainee notification system

Every payment-affecting change on a trainee's account triggers a confirmation email. The design principle: trainees should never wonder if a payment was received or where they stand. Proactive communication builds trust.

What triggers a notification

What does NOT trigger a notification

Sample email — payment received

Subject: Brotherhood Fishing Trip — Payment received ($175.00)

Hi Bob,

Just recorded a payment on your Brotherhood Fishing Trip account:

  Payment:       $175.00 (Cash)
  Date received: 2026-07-03
  Notes:         Handed to Rothstein at Bible study

Updated status:
  Trip cost:     $175.00
  Total paid:    $175.00
  Balance due:   $0.00
  Status:        ✓ GOOD TO GO

Keeping you in the loop. Reply if anything looks off.

— Brotherhood Fishing Trip

Sample email — correction

Subject: Brotherhood Fishing Trip — Correction to your account

Hi Bob,

We removed a payment entry ($175.00) from your Brotherhood Fishing Trip
account. This happens when something was recorded in error, reconciled
differently, or corrected.

Updated status:
  Trip cost:     $175.00
  Total paid:    $0.00
  Balance due:   $175.00
  Status:        No payments on file

If this looks wrong, reply and we'll sort it out.

— Brotherhood Fishing Trip

Opt-out mechanisms

Missing email handling

If a trainee has no email address on file, the notification is silently skipped. On recon saves you get a summary alert: "Save succeeded, but 2 trainee notifications could not be sent — no email on file." Reach those people via SMS or phone.

Audit trail

Every notification goes through the same brotherhood-send-comm edge function as regular Communications. Every send lands in brotherhood_communications. You can search send history to see when Bob's confirmation went out, what the exact subject and body were, and whether delivery succeeded.

13The System Map — self-documenting diagram tab

The System Map is a hidden-by-default tab (visible to super_user) that describes every architectural piece of the dashboard in plain language. It exists so that when you hand this system off to someone else — or when you come back after a year and forget how something works — the documentation lives inside the app.

Cards on the System Map cover: who can sign in, how "who's online" is tracked, the audit trail, concurrent-edit protection, data freshness, the Supabase schema, mobile responsiveness, deploy flow, reminder-email pipeline, bank cross-checks, read-only Paid column, Communications tab walkthrough, Recruiting tab walkthrough, sponsor propagation, per-core-member nudges, SMS launcher, manual payment ledger, trainee notifications, Treasury, Trip Expenses, receipt snap workflow, bank-debit reconciliation, and archived-signup re-signup handling.

The map is not a replacement for this manual — it's the developer-facing view of the same system. When something changes, both should be updated together.

14Business rules and invariants

These are the assumptions baked into the code. Changing any of them requires a code change; none can be tuned from the UI.

Money

Identity

Payment aggregation

Archiving

Concurrency

15Data model — where everything lives

The dashboard talks to a single Supabase project. Every write goes through Cloudflare Functions using the service key; the client never touches the database directly except for auth. Here are the tables that matter:

TablePurpose
fishing_signupsOne row per trainee who filled out the Jotform.
fishing_trip_paymentsThe legacy manual-paid flag per signup; also holds archived state.
brotherhood_bank_transactionsEvery row of every imported bank statement. Unique on (date, description, amount, balance).
brotherhood_bank_allocationsCategorized splits of bank transactions AND manual payments. The unified ledger.
brotherhood_dues_membersThe fixed core-member roster.
brotherhood_dues_paymentsCross-writes from dues_annual and dues_monthly allocations. Cell = (member_id, year, month).
brotherhood_configEditable key-value store. Currently holds the carryover figure.
brotherhood_trip_expensesOne row per receipt logged on the Trip Expenses tab.
brotherhood_usersDashboard user roles. Role = pending / user / manager / super_user.
brotherhood_communicationsLog of every email/SMS batch sent through the Communications tab.
brotherhood_communication_templatesReusable subject + body templates.
brotherhood_prospectsPre-signup pipeline. One row per potential attendee.
brotherhood_audit_logEvery mutation across the dashboard. Read from the Audit Log tab.

The unified allocation model

The brotherhood_bank_allocations table is worth understanding in detail because it's the heart of the payment system:

id                     uuid       primary key
transaction_id         uuid       FK to brotherhood_bank_transactions, NULLABLE
category               text       from the category set
amount                 numeric    positive
signup_id              text       FK-ish to fishing_signups.submission_id
member_id              uuid       FK to brotherhood_dues_members
fiscal_year            integer
month                  integer
notes                  text
payment_method         text       cash / venmo / cashapp / zelle_external / check / other
payment_date           date       when a manual payment was received
deposit_transaction_id uuid       FK to brotherhood_bank_transactions
created_at             timestamptz

A row must have EITHER transaction_id (bank origin) OR payment_method (manual origin) — never both, never neither. Enforced by a CHECK constraint. When a manual payment gets deposited, its deposit_transaction_id gets set to the bank txn representing the deposit — establishing a many-to-one link.

16Troubleshooting and recovery

"My session is not loading"

Cause is almost always cache. Force-refresh: on iOS Safari, tap-and-hold the reload icon → Request Website. On desktop, Cmd+Shift+R (Mac) or Ctrl+Shift+R (Windows). If it still doesn't load, the Cloudflare deploy may not have completed — wait 60 seconds and try again.

"The paid checkbox is green but Trip Status shows unpaid"

Legacy manual paid flag with no reconciled money behind it. Open the Reconciliation tab and find the bank credit that corresponds to this person's payment, then allocate it as fishing_trip → them. The green checkmark and Trip Status will reconcile once the allocation exists.

"Someone is showing an overage"

You reconciled more than $175 to them. Open their card, click through to see all transactions attached, and either: (a) refund the excess and remove the extra allocation, (b) reassign the excess to other_income, or (c) roll it to next year manually with a note.

"I recorded a manual payment but the deposit hasn't happened yet"

This is the expected state. The manual payment counts toward Cash on Hand on the Treasury tab. When you eventually deposit the cash, reconcile the bank credit as cash_deposit and check off the specific manual payments the deposit represents (chapter 5).

"I accidentally reconciled a deposit as fishing_trip instead of cash_deposit"

Now the trainee is showing paid twice — once from the manual payment, once from the bank credit. On the Reconciliation tab, expand that bank credit, delete the fishing_trip allocation, and re-save as cash_deposit with the appropriate rows checked. The trip status will correct itself.

"A trainee didn't get their confirmation email"

Check the Communications tab send history for their name and the time you saved. If the send row exists with an error, follow up on the SMTP failure (usually a Gmail rate limit — send fewer at once). If the send row doesn't exist, the notification was skipped — either the trainee has no email on file, or you unchecked the Email checkbox on the record-payment modal.

"The bank balance number is wrong"

The Bank Balance tile reads the balance column of the most recent bank transaction. If it looks wrong, you probably haven't imported the latest statement — or the latest import didn't include a balance column. Re-export from Truist including the running balance.

"Cash on Hand is not matching what's in my wallet"

List the manual payments in the Cash Ledger panel and reconcile against your physical stack. Either (a) a payment was recorded but the physical cash was already deposited (mark it deposited via cash_deposit reconciliation) or (b) you have cash that wasn't recorded (record it via the 💰 button on the appropriate person's card).

17Glossary

TermDefinition
AllocationA row in brotherhood_bank_allocations. Represents a specific dollar amount attributed to a specific category, and optionally a specific person.
Bank BalanceThe dollar figure the bank shows in the account right now. Derived from the latest imported bank transaction's balance column.
Cash on HandManual payments received but not yet deposited to the bank. Includes cash, Venmo balance, uncashed checks, etc.
cash_depositAllocation category that links a bank credit to specific undeposited manual payments. Does not count as income.
Core memberOne of the eight named Brotherhood brothers listed in brotherhood_dues_members. Owes $120/year in dues. Sees a star (⭐) next to their name on the roster.
Fiscal yearThe Brotherhood's financial year runs March through February. Fiscal 2026 = Mar 2026 through Feb 2027.
Manual paymentMoney received outside the bank channel (cash, Venmo, Cash App, check). Recorded via the 💰 Record payment button. Sits on the Cash on Hand ledger until deposited.
Net BrotherhoodTotal assets across bank and cash on hand. Formula: carryover + reconciled income − trip expenses.
NudgeA pipeline-review email sent to a core member listing their currently active prospects and status.
OverageAmount reconciled in excess of the $175 trip cost for a single person.
ProspectA pre-signup pipeline entry. Someone a core member is trying to bring in.
ReconciliationThe act of categorizing a bank transaction — telling the system what it was for.
SignupA row in fishing_signups. Created by the Jotform webhook when someone fills out the form.
SponsorThe core member who recruited a specific signup. Free-text but restricted by the UI picker.
Trip cost$175 per trainee, hard-coded across the system.
TraineeA trip participant. Includes core members who sign up AND non-members.

Brotherhood Fishing Trip Dashboard · Operator's Manual · Save this page for offline reading.
For questions or corrections, message the trip coordinator.