What Programs can and cannot account for
The Programs module has a complete financial design: funders, grants with reporting requirements, allocations of grant money to programs by fiscal year, per-program budgets, categorised line items, and expenses posted against those line items with a vendor and a receipt reference.
This page is about what happens to a figure once it is entered, and it has a short answer.
Every money figure in the Programs module is written exactly as typed. Two are worked out from something else, a budget's allocated total and its spent total, and each has exactly one writer. Nothing reconciles any figure against any other, in either direction:
- A program's allocations are never compared with its budget.
- A grant's allocations are never compared with the grant's own amount.
- A budget's line items are never compared with its total.
- An expense is never compared with the line item's remaining balance.
- A budget's spent total is never recalculated from its own expenses.
There is no reconciliation screen, no recalculation path, and, because this module runs no background task at all, nothing that could run one on a schedule.
The intended chain, and where each link is broken
Read the data model on its own and the intended design is legible and sensible. Here it is, with the state of each link.
| # | Link | State |
|---|---|---|
| 1 | A funder is recorded | No screen. Reachable from nowhere |
| 2 | A grant is recorded against the funder | No screen |
| 3 | The grant's reporting obligations are recorded | No screen |
| 4 | Grant money is allocated to a program for a fiscal year | No screen |
| 5 | The program gets a budget for that fiscal year | Works |
| 6 | The budget is split into categorised line items | No screen. Reachable from nowhere |
| 7 | Expenses are posted against the budget and a line item | Partly works, expenses can be recorded, but never against a line item |
| 8 | The budget is approved | No screen. Reachable from nowhere |
| 9 | Each expense is approved and paid | No writer anywhere. Every expense is Pending forever |
Links 5 and 7 are the only two a person can reach. A budget and its expenses are the whole of what PTRS can currently account for, and neither is connected to where the money came from or to any approval.
The three totals on a budget
A budget carries a total, an allocated figure and a spent figure, and the Budget tab prints all three plus a worked-out remaining figure.
Total
Typed into the New Budget dialog as dollars and saved. Free text; no rule of any kind exists in this subset, so it may be zero or negative.
Allocated, permanently zero
The allocated figure is written by one place in the whole solution: a genuine recalculation from the line items being saved, and it is correct. It is also reachable from no screen, so the Allocated card reads $0.00 for every budget in every organisation, and the Line Items table below it never renders.
Spent, real, but it means "entered", not "approved"
The spent figure is also written by one place: an increase by the expense's amount, each time Record Expense is used. Two properties of it matter.
It is an increase, not a recalculation. Nothing ever works the total out fresh from the expenses on file. If a row is ever removed or changed by any path other than Record Expense, and no such path exists today, the two figures diverge permanently and silently.
It counts unapproved expenses. An expense's status starts Pending and no code anywhere changes it. Approved, rejected, paid and voided are all unreachable. So Spent on a program's budget means someone typed this into a box, and there is no state in which it means anything stronger.
The same action does the module's one piece of two-level accounting: when an expense names a line item, it also increases that line item's own spent figure. Correct, and unreachable in practice, because nothing can create a line item for an expense to name.
Remaining
Worked out on the screen as total minus spent. It is therefore correct given the two figures it uses, and it ignores the allocated figure entirely.
The failure mode that is waiting
A line-item editor is the obvious next thing to build on this screen; it is the only reason the allocated figure and the Line Items table exist. When it is built, the existing action behind it will do this:
- Remove every line item on the budget.
- Save the submitted items as new records, each starting at zero spent.
- Recalculate the allocated figure from those new records.
- Leave the budget's own spent figure untouched.
Meanwhile every expense that named a removed line item has its link cleared rather than removed, because that relationship is set up to detach rather than cascade.
The expenses survive, which is better than the alternative, but after any edit to a budget's line items:
- the budget still reports the full amount spent;
- every line item reports zero spent;
- no expense is attributable to any category line;
- and there is no way to reattach them, because that link is only set at creation and there is no action to correct an expense afterward.
Editing a category name once would silently destroy the categorisation of every expense on that budget.
Nothing is broken today, because the action behind it is reachable from no screen. The reason it belongs here is that the defect is in the logic itself, not in the missing screen, so building the obvious screen, correctly, against this logic as it stands is enough to cause it.
Where the money was supposed to come from
Steps 1 to 4 of the chain, funder, grant, requirements, allocation, are ten actions across three areas, and not one of them is reachable from any screen. There is no funding sources screen, no grants screen and no allocations panel anywhere in PTRS.
The underlying logic is not a stub. Creating a funding allocation checks the program, the funding source, and the grant if one is given, refusing each by name if missing. Reading a grant's detail returns its requirements in order. A grant distinguishes its full amount from what has actually been received, exactly the distinction a funder report needs.
What is missing is any screen, and any arithmetic. The received amount is typed, not worked out from anything; nothing sums allocations; and nothing compares a grant's allocations with its own amount.
A grant requirement has a due date and a flag for whether it has been met, the shape of a funder reporting calendar. The only action that would set it is reachable from no screen.
Even if it were, nothing would act on the dates. This module runs no scheduled task, no background service, no live update, and no automatic reaction to anything. Of the twelve recurring jobs PTRS runs, none belongs to Programs.
So a missed grant reporting deadline has no mechanism in PTRS that could surface it.
Partner contributions are recorded and never valued
A partner contribution carries a type, financial, in kind, volunteer, equipment, facility, expertise, materials, or other, and an optional value. It is the natural place to record the match funding and in-kind support a grant application has to evidence.
Both of its actions are reachable from no screen, and no code in the solution sums the value. The Partnerships tab shows a count of contributions per partnership and never a value. Nothing rolls contributions into the program's budget, into a grant's match, or into any report.
What a person can actually produce
| A funder or auditor asks for | PTRS can produce |
|---|---|
| The program's approved budget for the fiscal year | A budget total, marked Draft, approval is unreachable |
| That budget broken down by category | Nothing. Line items cannot be created |
| Expenditure to date against the budget | A total, and a list of expenses with vendor, date, category and amount |
| Expenditure by category | Only by reading the expense list by hand; nothing groups them |
| Which expenses have been approved | Nothing. Every expense is Pending |
| Which grant is funding this program | Nothing. Allocations cannot be created |
| How much of the grant has been drawn down | Nothing |
| Progress against grant reporting requirements | Nothing |
| The value of partner contributions | Nothing. Values are stored and never summed |
| Who approved the budget, and when | Nothing, the columns exist and have no writer |
| Who approved the program's charter, and when | This one works, with a full approval history |
The one thing on this side that works, and is worth protecting
The charter approval workflow. Create, then submit, then review is guarded at both moves, writes a real approval-history entry with the reviewer and the time, records who approved it and when only on approval, and logs the action. Its action requires a setting that excludes the site director whose program it is.
It is the first workflow in the Programs module that completes end to end, and the second real approval control found anywhere in PTRS, after CACFP's claim approval. See Approve your first program charter and Program funding & charter approval.
Its one gap is that the separation of duties is at the level of the role, not the person: an organisation administrator can approve a charter they wrote themselves.
Related
- What Programs can and cannot measure, the same question for outcomes rather than money, and the same answer.
- Who can do what with money and governance
- Program funding & charter approval
Checked against PTRS on 7 September 2026.