Saltar al contenido principal

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.

A program's budget total is a number someone typed, and nothing checks it against anything

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.

#LinkState
1A funder is recordedNo screen. Reachable from nowhere
2A grant is recorded against the funderNo screen
3The grant's reporting obligations are recordedNo screen
4Grant money is allocated to a program for a fiscal yearNo screen
5The program gets a budget for that fiscal yearWorks
6The budget is split into categorised line itemsNo screen. Reachable from nowhere
7Expenses are posted against the budget and a line itemPartly works, expenses can be recorded, but never against a line item
8The budget is approvedNo screen. Reachable from nowhere
9Each expense is approved and paidNo 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:

  1. Remove every line item on the budget.
  2. Save the submitted items as new records, each starting at zero spent.
  3. Recalculate the allocated figure from those new records.
  4. 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.

Why this is documented now rather than left for the change that triggers it

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.

Grant reporting deadlines cannot be entered, so nothing can chase them

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 forPTRS can produce
The program's approved budget for the fiscal yearA budget total, marked Draft, approval is unreachable
That budget broken down by categoryNothing. Line items cannot be created
Expenditure to date against the budgetA total, and a list of expenses with vendor, date, category and amount
Expenditure by categoryOnly by reading the expense list by hand; nothing groups them
Which expenses have been approvedNothing. Every expense is Pending
Which grant is funding this programNothing. Allocations cannot be created
How much of the grant has been drawn downNothing
Progress against grant reporting requirementsNothing
The value of partner contributionsNothing. Values are stored and never summed
Who approved the budget, and whenNothing, the columns exist and have no writer
Who approved the program's charter, and whenThis 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.

Checked against PTRS on 7 September 2026.