Board Treasurer's Report - Instant Demo
The monthly board report from QuickBooks: surplus or deficit for the last 12 months against the 12 before, the accounts that moved, months of cash on hand, what is owed within a year, and how much revenue rests on one source.
9 steps · shared by Klajdi · September 21, 2026
No data is shared in this template. It contains only the recipe — column names and SQL logic. When you run it, your data is processed in your own browser and never leaves your machine.
What data it expects
QBO_ProfitAndLoss_Month.csv
section · VARCHARaccount · VARCHAR<one column per month, YYYY-MM> · DOUBLE
QBO_TrialBalance.csv
account · VARCHARtype · VARCHARdebit · DOUBLEcredit · DOUBLE
Connect QuickBooks Online or drop a CSV / Excel export with a similar layout — the AI adapts the workflow if your columns differ.
How it works — every step, readable
- 01Demo shelter - last 24 months of profit and loss (sample)
SELECT section, account, CAST(COLUMNS(* EXCLUDE (section, account)) AS DOUBLE) FROM (VALUES ('Income', 'Donations & contributions', 90307.0, 94109.4, 97911.8, 91257.6, 114072.0, 98862.4, 92208.2, 96010.6, 99813.0, 93158.8, 145441.8, 207706.1, 97020.0, 100940.0, 94080.0, 98000.0, 122304.0, 95060.0, 98980.0, 102900.0, 96040.0, 99960.0, 139650.0, 223146.0, 2688938.7), ('Income', 'Grants', 24339.0, 25363.8, 68610.36, 24595.2, 25620.0, 26644.8, 24851.4, 25876.2, 59182.2, 25107.6, 26132.4, 24339.0, 20790.0, 21630.0, 52416.0, 21000.0, 21840.0, 20370.0, 21210.0, 22050.0, 45276.0, 21420.0, 19950.0, 20790.0, 689403.96), ('Income', 'Adoption fees', 12810.75, 13350.15, 13889.55, 12945.6, 13485.0, 18231.72, 17658.61, 17024.81, 14159.25, 13215.3, 13754.7, 12810.75, 14355.0, 14935.0, 13920.0, 14500.0, 15080.0, 18284.5, 19770.75, 19031.25, 14210.0, 14790.0, 13775.0, 14355.0, 360342.69), ('Income', 'Clinic & program service fees', 9864.8, 10280.16, 10695.52, 9968.64, 10384.0, 10799.36, 10072.48, 10487.84, 10903.2, 10176.32, 10591.68, 9864.8, 11682.0, 12154.0, 11328.0, 11800.0, 12272.0, 11446.0, 11918.0, 12390.0, 11564.0, 12036.0, 11210.0, 11682.0, 265570.8), ('Income', 'Special events', 7467.0, 7781.4, 8095.8, 22636.8, 7860.0, 8174.4, 7624.2, 7938.6, 8253.0, 42365.4, 8017.2, 7467.0, 5940.0, 6180.0, 5760.0, 18000.0, 6240.0, 5820.0, 6060.0, 6300.0, 5880.0, 33660.0, 5700.0, 5940.0, 255160.8), ('Other Income', 'Investment income', 1444.0, 1504.8, 1565.6, 1459.2, 1520.0, 1580.8, 1474.4, 1535.2, 1596.0, 1489.6, 1550.4, 1444.0, 1881.0, 1957.0, 1824.0, 1900.0, 1976.0, 1843.0, 1919.0, 1995.0, 1862.0, 1938.0, 1805.0, 1881.0, 40945.0), ('Expenses', 'Salaries & wages', 74404.0, 77536.8, 80669.6, 75187.2, 78320.0, 81452.8, 75970.4, 79103.2, 82236.0, 76753.6, 79886.4, 74404.0, 87120.0, 90640.0, 84480.0, 88000.0, 91520.0, 85360.0, 88880.0, 92400.0, 86240.0, 89760.0, 83600.0, 87120.0, 1991044.0), ('Expenses', 'Executive Director salary', 8755.2, 9123.84, 9492.48, 8847.36, 9216.0, 9584.64, 8939.52, 9308.16, 9676.8, 9031.68, 9400.32, 8755.2, 9504.0, 9888.0, 9216.0, 9600.0, 9984.0, 9312.0, 9696.0, 10080.0, 9408.0, 9792.0, 9120.0, 9504.0, 225235.2), ('Expenses', 'Payroll taxes & benefits', 14711.7, 15331.14, 15950.58, 14866.56, 15486.0, 16105.44, 15021.42, 15640.86, 16260.3, 15176.28, 15795.72, 14711.7, 17622.0, 18334.0, 17088.0, 17800.0, 18512.0, 17266.0, 17978.0, 18690.0, 17444.0, 18156.0, 16910.0, 17622.0, 398479.7), ('Expenses', 'Animal care & veterinary supplies', 21147.0, 22037.4, 22927.8, 21369.6, 22260.0, 27780.48, 26990.25, 22482.6, 23373.0, 21814.8, 22705.2, 21147.0, 26235.0, 27295.0, 25440.0, 26500.0, 27560.0, 30846.0, 33456.25, 27825.0, 25970.0, 27030.0, 25175.0, 26235.0, 605602.38), ('Expenses', 'Occupancy & utilities', 13988.75, 13994.64, 12133.4, 11308.8, 11780.0, 12251.2, 11426.6, 11897.8, 12369.0, 11544.4, 12015.6, 13429.2, 15345.0, 15326.4, 11904.0, 12400.0, 12896.0, 12028.0, 12524.0, 13020.0, 12152.0, 12648.0, 11780.0, 14731.2, 304893.99), ('Expenses', 'Fundraising events & mailings', 7660.8, 7983.36, 8305.92, 7741.44, 8064.0, 8386.56, 7822.08, 8144.64, 8467.2, 25288.7, 13160.45, 7660.8, 7128.0, 7416.0, 6912.0, 7200.0, 7488.0, 6984.0, 7272.0, 7560.0, 7056.0, 23500.8, 10944.0, 7128.0, 225274.75), ('Expenses', 'Professional fees', 4003.3, 4171.86, 4340.42, 9709.06, 4214.0, 4382.56, 4087.58, 4256.14, 4424.7, 4129.72, 4298.28, 4003.3, 4257.0, 4429.0, 4128.0, 10320.0, 4472.0, 4171.0, 4343.0, 4515.0, 4214.0, 4386.0, 4085.0, 4257.0, 113597.92), ('Expenses', 'Insurance', 2679.95, 2792.79, 2905.63, 2708.16, 2821.0, 2933.84, 2736.37, 2849.21, 2962.05, 2764.58, 2877.42, 2679.95, 3069.0, 3193.0, 2976.0, 3100.0, 3224.0, 3007.0, 3131.0, 3255.0, 3038.0, 3162.0, 2945.0, 3069.0, 70879.95), ('Expenses', 'Depreciation', 4940.0, 5148.0, 5356.0, 4992.0, 5200.0, 5408.0, 5044.0, 5252.0, 5460.0, 5096.0, 5304.0, 4940.0, 5148.0, 5356.0, 4992.0, 5200.0, 5408.0, 5044.0, 5252.0, 5460.0, 5096.0, 5304.0, 4940.0, 5148.0, 124488.0), ('Other Expenses', 'Interest expense', 1179.9, 1229.58, 1279.26, 1192.32, 1242.0, 1291.68, 1204.74, 1254.42, 1304.1, 1217.16, 1266.84, 1179.9, 1138.5, 1184.5, 1104.0, 1150.0, 1196.0, 1115.5, 1161.5, 1207.5, 1127.0, 1173.0, 1092.5, 1138.5, 28630.4) ) AS t(section, account, "2024-09", "2024-10", "2024-11", "2024-12", "2025-01", "2025-02", "2025-03", "2025-04", "2025-05", "2025-06", "2025-07", "2025-08", "2025-09", "2025-10", "2025-11", "2025-12", "2026-01", "2026-02", "2026-03", "2026-04", "2026-05", "2026-06", "2026-07", "2026-08", "Total") - 02Demo shelter - trial balance at month-end (sample)
SELECT account_number, account, type, CAST(debit AS DOUBLE) AS debit, CAST(credit AS DOUBLE) AS credit FROM (VALUES ('', 'Operating checking', 'Balance Sheet', 184300, NULL), ('', 'Savings - operating reserve', 'Balance Sheet', 412000, NULL), ('', 'Restricted cash - capital campaign', 'Balance Sheet', 96500, NULL), ('', 'Grants & pledges receivable', 'Balance Sheet', 138200, NULL), ('', 'Prepaid expenses', 'Balance Sheet', 21400, NULL), ('', 'Buildings & equipment', 'Balance Sheet', 2140000, NULL), ('', 'Accumulated depreciation', 'Balance Sheet', NULL, 684000), ('', 'Accounts payable', 'Balance Sheet', NULL, 58700), ('', 'Accrued payroll & PTO', 'Balance Sheet', NULL, 71900), ('', 'Credit card', 'Balance Sheet', NULL, 9800), ('', 'Deferred revenue - grants', 'Balance Sheet', NULL, 64000), ('', 'Mortgage payable', 'Balance Sheet', NULL, 512000), ('', 'Net assets with donor restrictions', 'Balance Sheet', NULL, 234700), ('', 'Net assets without donor restrictions', 'Balance Sheet', NULL, 1365167.65), ('', 'Donations & contributions', 'Income Statement', NULL, 1368080.0), ('', 'Grants', 'Income Statement', NULL, 308742.0), ('', 'Adoption fees', 'Income Statement', NULL, 187006.5), ('', 'Clinic & program service fees', 'Income Statement', NULL, 141482.0), ('', 'Special events', 'Income Statement', NULL, 111480.0), ('', 'Investment income', 'Income Statement', NULL, 22781.0), ('', 'Salaries & wages', 'Income Statement', 1055120.0, NULL), ('', 'Executive Director salary', 'Income Statement', 115104.0, NULL), ('', 'Payroll taxes & benefits', 'Income Statement', 213422.0, NULL), ('', 'Animal care & veterinary supplies', 'Income Statement', 329567.25, NULL), ('', 'Occupancy & utilities', 'Income Statement', 156754.6, NULL), ('', 'Fundraising events & mailings', 'Income Statement', 106588.8, NULL), ('', 'Professional fees', 'Income Statement', 57577.0, NULL), ('', 'Insurance', 'Income Statement', 37169.0, NULL), ('', 'Depreciation', 'Income Statement', 62348.0, NULL), ('', 'Interest expense', 'Income Statement', 13788.5, NULL) ) AS t(account_number, account, type, debit, credit) - 03Line up the last 12 months and the 12 beforecombines data from multiple inputs · buckets values by condition · computes running / windowed totals
WITH long AS ( UNPIVOT (SELECT * FROM input_1) ON COLUMNS(* EXCLUDE (section, account)) INTO NAME period VALUE amount ), m AS (SELECT DISTINCT period FROM long WHERE regexp_matches(period, '^[0-9]{4}-[0-9]{2}$')), r AS (SELECT period, ROW_NUMBER() OVER (ORDER BY period DESC) AS months_back FROM m) SELECT l.section, l.account, l.period, ROUND(l.amount, 2) AS amount, CASE WHEN r.months_back <= 12 THEN 'Last 12 months' WHEN r.months_back <= 24 THEN 'Prior 12 months' ELSE 'Older' END AS time_window, r.months_back = 1 AS is_latest_month, CASE WHEN l.section ILIKE '%income%' THEN 'Revenue' ELSE 'Expense' END AS kind FROM long l JOIN r ON r.period = l.period WHERE l.account NOT ILIKE 'total %' AND l.amount IS NOT NULL ORDER BY l.period, l.section, l.account - 04SUMMARY P&L - latest month, last 12 months, the 12 beforeaggregates rows into summary totals · buckets values by condition · appends result sets (e.g. a TOTAL row)
WITH s AS ( SELECT section, kind, COALESCE(SUM(amount) FILTER (WHERE is_latest_month), 0) AS latest_month, COALESCE(SUM(amount) FILTER (WHERE time_window = 'Last 12 months'), 0) AS last_12_months, COALESCE(SUM(amount) FILTER (WHERE time_window = 'Prior 12 months'), 0) AS prior_12_months FROM input_1 GROUP BY section, kind ), w AS (SELECT MAX(period) AS latest_period, COUNT(DISTINCT period) FILTER (WHERE time_window = 'Last 12 months') AS months_in_last_12, COUNT(DISTINCT period) FILTER (WHERE time_window = 'Prior 12 months') AS months_in_prior_12 FROM input_1), lines AS ( SELECT CASE WHEN kind = 'Revenue' THEN 1 ELSE 3 END AS ord, section AS line_item, latest_month, last_12_months, prior_12_months FROM s UNION ALL SELECT 2, 'TOTAL REVENUE', SUM(latest_month), SUM(last_12_months), SUM(prior_12_months) FROM s WHERE kind = 'Revenue' UNION ALL SELECT 4, 'TOTAL EXPENSES', SUM(latest_month), SUM(last_12_months), SUM(prior_12_months) FROM s WHERE kind = 'Expense' UNION ALL SELECT 5, 'SURPLUS (DEFICIT)', SUM(CASE WHEN kind = 'Revenue' THEN latest_month ELSE -latest_month END), SUM(CASE WHEN kind = 'Revenue' THEN last_12_months ELSE -last_12_months END), SUM(CASE WHEN kind = 'Revenue' THEN prior_12_months ELSE -prior_12_months END) FROM s ) SELECT l.line_item, ROUND(l.latest_month, 0) AS latest_month, ROUND(l.last_12_months, 0) AS last_12_months, CASE WHEN w.months_in_prior_12 = 12 THEN ROUND(l.prior_12_months, 0) END AS prior_12_months, CASE WHEN w.months_in_prior_12 = 12 THEN ROUND(l.last_12_months - l.prior_12_months, 0) END AS change, CASE WHEN w.months_in_prior_12 = 12 THEN ROUND(100.0 * (l.last_12_months - l.prior_12_months) / NULLIF(ABS(l.prior_12_months), 0), 1) END AS change_pct, w.latest_period AS latest_month_is, w.months_in_last_12, w.months_in_prior_12 FROM lines l, w ORDER BY l.ord, l.last_12_months DESC - 05What moved - the accounts behind the changeaggregates rows into summary totals · buckets values by condition · filters to the relevant rows
WITH a AS ( SELECT kind, account, COALESCE(SUM(amount) FILTER (WHERE time_window = 'Last 12 months'), 0) AS last_12_months, COALESCE(SUM(amount) FILTER (WHERE time_window = 'Prior 12 months'), 0) AS prior_12_months FROM input_1 GROUP BY kind, account ), w AS (SELECT COUNT(DISTINCT period) FILTER (WHERE time_window = 'Prior 12 months') AS months_in_prior_12 FROM input_1) SELECT a.kind, a.account, ROUND(a.last_12_months, 0) AS last_12_months, ROUND(a.prior_12_months, 0) AS prior_12_months, ROUND(a.last_12_months - a.prior_12_months, 0) AS change, ROUND(100.0 * (a.last_12_months - a.prior_12_months) / NULLIF(ABS(a.prior_12_months), 0), 1) AS change_pct, CASE WHEN a.kind = 'Revenue' AND a.last_12_months >= a.prior_12_months THEN 'Helps the bottom line' WHEN a.kind = 'Expense' AND a.last_12_months <= a.prior_12_months THEN 'Helps the bottom line' ELSE 'Hurts the bottom line' END AS effect FROM a, w WHERE w.months_in_prior_12 = 12 AND a.last_12_months <> a.prior_12_months ORDER BY ABS(a.last_12_months - a.prior_12_months) DESC LIMIT 8 - 06Where the money comes fromaggregates rows into summary totals · computes running / windowed totals · filters to the relevant rows
WITH a AS ( SELECT account, SUM(amount) AS last_12_months FROM input_1 WHERE kind = 'Revenue' AND time_window = 'Last 12 months' GROUP BY account HAVING SUM(amount) > 0 ), t AS (SELECT SUM(last_12_months) AS total FROM a) SELECT ROW_NUMBER() OVER (ORDER BY a.last_12_months DESC) AS rank, a.account AS revenue_source, ROUND(a.last_12_months, 0) AS last_12_months, ROUND(100.0 * a.last_12_months / NULLIF(t.total, 0), 1) AS share_of_revenue_pct, ROUND(100.0 * SUM(a.last_12_months) OVER (ORDER BY a.last_12_months DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) / NULLIF(t.total, 0), 1) AS running_share_pct FROM a, t ORDER BY a.last_12_months DESC - 07Cash, receivables and what is owed (check this step)buckets values by condition · filters to the relevant rows · sorts the output
WITH t AS ( SELECT account, COALESCE(debit, 0) - COALESCE(credit, 0) AS balance FROM input_1 WHERE type = 'Balance Sheet' OR type IS NULL OR type = '' ) SELECT account, ROUND(balance, 2) AS balance, CASE WHEN balance > 0 AND regexp_matches(lower(account), 'restricted|endowment|capital campaign|escrow|custod') AND regexp_matches(lower(account), 'cash|checking|saving|bank|money market|fund|invest') THEN 'Restricted or set-aside cash' WHEN balance > 0 AND regexp_matches(lower(account), 'cash|checking|saving|bank|money market|operating acc|reserve|paypal|stripe|undeposited') THEN 'Operating cash' WHEN balance > 0 AND regexp_matches(lower(account), 'receivable|pledge') THEN 'Receivables' WHEN balance < 0 AND regexp_matches(lower(account), 'payable|accrued|credit card|deferred|payroll liab|withh|sales tax|line of credit|refundable') AND NOT regexp_matches(lower(account), 'mortgage|loan|note') THEN 'Owed within a year' WHEN balance < 0 AND regexp_matches(lower(account), 'mortgage|loan|note') THEN 'Long-term debt' ELSE 'Other' END AS bucket, 'Sorted by words in the account name - check it before the board sees the cash figures' AS note FROM t WHERE balance <> 0 ORDER BY CASE WHEN balance > 0 THEN 0 ELSE 1 END, ABS(balance) DESC - 08Months of cash on handfilters to the relevant rows
WITH c AS ( SELECT COALESCE(SUM(balance) FILTER (WHERE bucket = 'Operating cash'), 0) AS operating_cash, COALESCE(SUM(balance) FILTER (WHERE bucket = 'Restricted or set-aside cash'), 0) AS restricted_cash, COALESCE(SUM(balance) FILTER (WHERE bucket = 'Receivables'), 0) AS receivables, COALESCE(-SUM(balance) FILTER (WHERE bucket = 'Owed within a year'), 0) AS owed_within_a_year, COALESCE(-SUM(balance) FILTER (WHERE bucket = 'Long-term debt'), 0) AS long_term_debt FROM input_1 ), e AS ( SELECT SUM(amount) FILTER (WHERE kind = 'Expense' AND NOT regexp_matches(lower(account), 'depreciation|amortization')) AS cash_expenses, COUNT(DISTINCT period) AS months_counted FROM input_2 WHERE time_window = 'Last 12 months' ) SELECT ROUND(c.operating_cash, 0) AS operating_cash, ROUND(c.restricted_cash, 0) AS restricted_cash, ROUND(c.receivables, 0) AS receivables, ROUND(c.owed_within_a_year, 0) AS owed_within_a_year, ROUND(c.long_term_debt, 0) AS long_term_debt, ROUND(e.cash_expenses / NULLIF(e.months_counted, 0), 0) AS average_monthly_expenses_excl_depreciation, ROUND(c.operating_cash / NULLIF(e.cash_expenses / NULLIF(e.months_counted, 0), 0), 1) AS months_of_cash, ROUND(c.operating_cash - c.owed_within_a_year, 0) AS cash_after_what_is_owed, ROUND((c.operating_cash - c.owed_within_a_year) / NULLIF(e.cash_expenses / NULLIF(e.months_counted, 0), 0), 1) AS months_of_cash_after_what_is_owed FROM c, e - 09TREASURER'S REPORT - what to tell the boardbuckets values by condition · appends result sets (e.g. a TOTAL row) · filters to the relevant rows
WITH st AS (SELECT * FROM input_1), mv AS (SELECT * FROM input_2), lq AS (SELECT * FROM input_3), mx AS (SELECT * FROM input_4), rev AS (SELECT * FROM st WHERE line_item = 'TOTAL REVENUE'), exp AS (SELECT * FROM st WHERE line_item = 'TOTAL EXPENSES'), net AS (SELECT * FROM st WHERE line_item = 'SURPLUS (DEFICIT)'), movers AS (SELECT string_agg(account || ' ' || CASE WHEN change >= 0 THEN '+' ELSE '-' END || (CASE WHEN (ABS(change)) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(ABS(change))) AS BIGINT))), ', ') AS txt FROM (SELECT * FROM mv LIMIT 3)), top1 AS (SELECT revenue_source, share_of_revenue_pct FROM mx WHERE rank = 1), top2 AS (SELECT running_share_pct FROM mx WHERE rank = 2), rows_out AS ( SELECT 1 AS ord, 'BOTTOM LINE' AS area, (SELECT CASE WHEN net.last_12_months >= 0 THEN 'Surplus of ' ELSE 'Deficit of ' END || (CASE WHEN (ABS(net.last_12_months)) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(ABS(net.last_12_months))) AS BIGINT))) || ' over the last ' || net.months_in_last_12 || ' months on revenue of ' || (CASE WHEN (rev.last_12_months) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(rev.last_12_months)) AS BIGINT))) || ' (' || (CAST(ROUND(100.0 * net.last_12_months / NULLIF(rev.last_12_months, 0), 1) AS VARCHAR) || '%') || ' of revenue)' || CASE WHEN net.prior_12_months IS NOT NULL THEN ' - the 12 months before: ' || CASE WHEN net.prior_12_months >= 0 THEN 'surplus of ' ELSE 'deficit of ' END || (CASE WHEN (ABS(net.prior_12_months)) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(ABS(net.prior_12_months))) AS BIGINT))) ELSE '' END FROM net, rev) AS finding, (SELECT CASE WHEN net.last_12_months < 0 THEN 'Deficit - the board will want the plan to close it' WHEN net.prior_12_months IS NOT NULL AND net.last_12_months < net.prior_12_months THEN 'Still a surplus, but smaller than the year before - see what moved' ELSE 'None needed - in surplus' END FROM net) AS next_step UNION ALL SELECT 2, 'REVENUE AND EXPENSES', (SELECT 'Revenue ' || CASE WHEN rev.change_pct >= 0 THEN 'up ' ELSE 'down ' END || (CAST(ROUND(ABS(rev.change_pct), 1) AS VARCHAR) || '%') || ' and expenses ' || CASE WHEN exp.change_pct >= 0 THEN 'up ' ELSE 'down ' END || (CAST(ROUND(ABS(exp.change_pct), 1) AS VARCHAR) || '%') || ' against the 12 months before' FROM rev, exp), (SELECT CASE WHEN exp.change_pct > rev.change_pct THEN 'Expenses are growing faster than revenue - walk the board through the movers below' ELSE 'None needed - revenue is growing at least as fast as expenses' END FROM rev, exp) FROM rev WHERE rev.change_pct IS NOT NULL UNION ALL SELECT 3, 'NOT ENOUGH HISTORY YET', (SELECT 'The books hold ' || months_in_last_12 + months_in_prior_12 || ' months - a year-over-year comparison needs 24' FROM rev), 'Activity only - the comparison columns fill in once 24 months are on the books' FROM rev WHERE rev.change_pct IS NULL UNION ALL SELECT 4, 'WHAT MOVED', (SELECT 'Largest changes: ' || txt FROM movers), 'Each one traces to its account in the step named What moved' FROM movers WHERE txt IS NOT NULL UNION ALL SELECT 5, 'LATEST MONTH', (SELECT rev.latest_month_is || ': revenue ' || (CASE WHEN (rev.latest_month) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(rev.latest_month)) AS BIGINT))) || ', expenses ' || (CASE WHEN (exp.latest_month) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(exp.latest_month)) AS BIGINT))) || ', ' || CASE WHEN net.latest_month >= 0 THEN 'surplus ' ELSE 'deficit ' END || (CASE WHEN (ABS(net.latest_month)) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(ABS(net.latest_month))) AS BIGINT))) FROM rev, exp, net), 'Activity only - one month is noisy; the 12-month figures carry the story' UNION ALL SELECT 6, 'CASH ON HAND', (SELECT 'Operating cash ' || (CASE WHEN (operating_cash) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(operating_cash)) AS BIGINT))) || ' = ' || months_of_cash || ' months of expenses' || CASE WHEN restricted_cash > 0 THEN ' (restricted cash of ' || (CASE WHEN (restricted_cash) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(restricted_cash)) AS BIGINT))) || ' left out)' ELSE '' END FROM lq), (SELECT CASE WHEN months_of_cash IS NULL THEN 'No cash accounts recognised - check the cash step' WHEN months_of_cash < 3 THEN 'Below the 3 months commonly cited as the floor for an operating reserve - the board should see the plan' WHEN months_of_cash <= 6 THEN 'None needed - inside the 3 to 6 months commonly cited for an operating reserve' ELSE 'None needed - above the 3 to 6 months commonly cited for an operating reserve' END FROM lq) UNION ALL SELECT 7, 'OWED WITHIN A YEAR', (SELECT 'Payables, accrued payroll, cards and deferred revenue total ' || (CASE WHEN (owed_within_a_year) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(owed_within_a_year)) AS BIGINT))) || ' - cash after those: ' || (CASE WHEN (cash_after_what_is_owed) < 0 THEN '-$' ELSE '$' END || format('{:,}', CAST(ROUND(ABS(cash_after_what_is_owed)) AS BIGINT))) || ' (' || months_of_cash_after_what_is_owed || ' months)' FROM lq), (SELECT CASE WHEN cash_after_what_is_owed < 0 THEN 'Short-term obligations exceed operating cash - flag it to the board now' ELSE 'None needed - operating cash covers what is owed within a year' END FROM lq) FROM lq WHERE owed_within_a_year > 0 UNION ALL SELECT 8, 'WHERE THE MONEY COMES FROM', (SELECT top1.revenue_source || ' brings in ' || (CAST(ROUND(top1.share_of_revenue_pct, 1) AS VARCHAR) || '%') || ' of revenue' || COALESCE('; the top two sources together ' || (CAST(ROUND((SELECT running_share_pct FROM top2), 1) AS VARCHAR) || '%'), '') FROM top1), (SELECT CASE WHEN share_of_revenue_pct > 50 THEN 'More than half of revenue rests on one source - worth a line in the board pack' ELSE 'None needed - no single source is more than half of revenue' END FROM top1) FROM top1 UNION ALL SELECT 99, 'VERDICT', (SELECT CASE WHEN net.last_12_months >= 0 THEN 'In surplus' ELSE 'In deficit' END || COALESCE(' with ' || lq.months_of_cash || ' months of cash', '') || CASE WHEN exp.change_pct > rev.change_pct THEN ' - expenses are growing faster than revenue' ELSE '' END FROM net, lq, rev, exp), 'Every figure traces to a QuickBooks account - re-run it before each board meeting' ) SELECT ord, area, finding, next_step FROM rows_out ORDER BY ord
Run this on your books
Free to try — no sign-up, no card. The workflow runs in your browser; your data never leaves your machine.
Make it your own →