Who can do what with money and governance
This page covers 33 things PTRS can do for a program's charter, budget and expenses, partners and partnerships, agreements and contributions, funding allocations, compliance requirements, documents and the national program pillars, all of which require only the module-wide setting.
The other six actions in this subset require a second, narrower setting, and are on their own page: Program funding & charter approval.
The denominator
The Programs module can do 122 things in total. This subset is 39 of them; this page covers 33 and the funding page covers the remaining six.
| Subset | Count | Where |
|---|---|---|
| Programs core, setup, lifecycle, scheduling, enrolment, consent, cohorts | 34 | Who can do what with a program's setup, schedule and enrolment |
| Programs delivery, curriculum, staffing, goals, assessment, surveys | 49 | Who can do what with curriculum, staffing, goals, assessments and surveys |
| Money and governance, requiring only the module-wide setting | 33 | this page |
| Money and governance, requiring a second setting | 6 | Program funding & charter approval |
| Module total | 122 |
The Programs module is now fully covered across these four pages.
Who is admitted
All 39 actions in this subset require the module-wide setting.
| Setting | Roles it admits |
|---|---|
| The module-wide setting, on all 39 | Site directors, regional directors, organisation administrators, super admins |
| The narrower membership setting, on the action every tab depends on | Staff, site directors, organisation administrators, super admins |
| Both together | Site directors, organisation administrators, super admins |
How the 39 break down
| Declaration | Count | Covered on |
|---|---|---|
| Restates the module-wide setting | 23 | this page |
| No setting beyond the module-wide one | 10 | this page |
| Requires the financial setting, narrower | 5 | the funding page |
| Requires the charter-approval setting, narrower | 1 | the funding page |
None in this subset is open with no sign-in check.
The ten with no setting beyond the module-wide one are all reads: a program's charters, one charter, a program's budgets, one budget, a budget's expenses, a program's funding allocations, all funding sources, all grants, one grant, and the national program pillars.
Creating or correcting a funding source or a grant requires the narrower financial setting, which excludes site directors. Reading them requires only the module-wide setting, which admits it. Reading grants and funding sources declares nothing narrower at all, so a site director can read every grant amount, every grant number, every award and end date, and every funding source's named contact and email, for the whole organisation, unpaged and unfiltered.
This is the mirror image of the Members module, where both reading and saving a child's financial information require the narrower setting. There, the read was protected. Here it is not.
What a role actually experiences
All five screens in this subset are tabs inside a program's own layout, and that layout loads the program's own detail before rendering any tab.
| Role | What they can actually reach |
|---|---|
| Site directors, organisation administrators, super admins | Every action on this page, and all five screens |
| Regional directors | Every action on this page by setting, and no screen. The layout shows a failure message in place of every tab, because the detail check refuses the role |
| Staff members | None. The module-wide setting excludes the role |
| Guardians, OCCL auditors, read-only accounts | None |
The five tabs are Charter, Budget, Partnerships, Compliance and Documents.
How to read the "Reachable" column
| Value | Meaning |
|---|---|
| A screen or component name | Something in the product calls this action in normal use |
| Nothing reaches it | The action is built correctly and no screen calls it |
Every one of the 39 actions in this subset already has the code that would call it, ready and waiting. Nothing is missing that layer. What is missing is the screen that would use it.
Summary
| Count | |
|---|---|
| Actions in the money and governance subset | 39 |
| Reachable by a screen | 14 |
| Reachable by nothing | 24 |
| Wired up and never reached | 1 |
| Require a second setting | 6 |
| Carry no setting beyond the module-wide one | 10 |
Charters (6 actions)
| Action | Reachable by | Note |
|---|---|---|
| Create a charter | The Charter tab | Creates it as a draft, version 1. The dialog collects title, mission, vision and scope; it does not send goals |
| Correct a charter | Nothing reaches it | The only path that can set an effective or expiry date, and the only way to edit a charter at all |
| Read one charter | Nothing reaches it | Reading a program's charters already returns the full record including approval history, so nothing needs this |
| Read a program's charters | The Charter tab | Ordered by version, always 1 |
| Submit a charter for approval | The Charter tab | Guarded: only from draft or rejected, otherwise refused by name |
| Approve or reject a charter | The Charter tab | See the funding and approval page |
The charter is the one flow in Programs that completes
Create, then submit, then approve is a real chain of stages with a real guard at each step, and it produces a correct record. Submitting refuses anything but a draft or a rejected charter; approving refuses anything not currently pending and any decision other than approved or rejected; and approval writes a real history entry with the reviewer, the time and the comments.
After eleven modules this is the first Programs workflow documented in this portal that finishes. It is also the subject of the module's only tutorial.
A charter has six possible stages. Four are reachable: draft on create, pending on submit, approved and rejected on review. Expired and superseded have no writer anywhere in the solution, and nothing reads a charter's expiry date to compare it with today. A charter that has expired on paper stays approved in PTRS forever.
PTRS defines two record types for a configurable, multi-step approval, a workflow and its steps, each with a required role, and neither has a reader or a writer anywhere in the solution. The only references are the underlying table declarations. Approving a charter always sets its approval-step link to nothing, regardless.
So a charter's approval is a single review by anyone holding the charter-approval setting, and the required-role column that would have made it configurable is never read.
Budgets, line items and expenses (7 actions)
| Action | Reachable by | Note |
|---|---|---|
| Create a budget | The Budget tab | Fiscal year is free text; the dialog's placeholder suggests a year range and nothing checks the shape |
| Correct a budget | Nothing reaches it | The only path that can approve a budget. No screen calls it, so every budget is permanently unapproved |
| Read a program's budgets | The Budget tab | Returns line-item and expense counts per budget, ordered by fiscal year, newest first |
| Read one budget | The Budget tab | Returns line items and expenses in full, plus who approved it and when |
| Set a budget's line items | Nothing reaches it | The only writer of a budget's allocated total. No screen calls it, so allocation is permanently zero |
| Record an expense | The Budget tab | The only writer of a budget's spent total |
| Read a budget's expenses | Nothing reaches it | Reading one budget already returns its expenses, so nothing needs this |
Who writes the three budget totals
A budget carries three money figures. Each has exactly one writer.
| Figure | Written by | How |
|---|---|---|
| Total budget | Creating or correcting a budget | Taken exactly as typed |
| Allocated | Setting line items only | A real recalculation from the line items just saved |
| Spent | Recording an expense only | An increase each time, never a recalculation from the expenses on file |
Recording an expense also increases the named line item's own spent figure, when one is named. That is the module's only two-level roll-up, and it is correct as written.
Nothing recalculates any of the three from scratch. There is no reconciliation path and no scheduled task. Once the spent figure diverges from the sum of the actual expenses, nothing in PTRS will notice or correct it, and the next section is how it diverges.
Setting a budget's line items replaces the whole set: every existing line item for the budget is removed, and the request's items are saved fresh in their place.
Three things follow, and they compound:
- Every new line item's own spent figure starts at zero. They are new records; the spending against the old ones is not carried over.
- Every expense that named one of the removed line items has its link cleared, so the expense survives, detached.
- The budget's own spent total is not touched. It still holds the running amount.
The budget therefore reports the same amount spent, no line item accounts for any of it, and every expense is now uncategorised at the line level. There is no way to reattach an expense to a line item; that link is only set at creation and there is no action to correct an expense afterward.
Dormant today, because setting line items is reachable from no screen. It becomes live the moment a line-item editor is built, which is the obvious next change to this screen.
An expense's status starts Pending and nothing anywhere ever changes it. Approved, rejected, paid and voided are all unreachable, and PTRS's own message for an invalid status has no path that would ever show it, because nothing accepts a status to check in the first place.
The consequence for the money: a budget's spent figure counts every expense the moment it is recorded, and no expense has ever been approved. Spent means entered.
A budget carries whether it is approved, who approved it, and when. Correcting a budget sets only the approved flag, from a plain yes or no in the request; it does not set who approved it or when, and nothing else does either.
So PTRS permits a budget marked approved with no approver and no time recorded, set by anyone holding the module-wide setting, with no record of who approved it. There is no guard on this and no separation of duties, unlike the charter.
Not reachable in the interface today, because no screen ever corrects a budget and the badge therefore always reads Draft. Reachable for anyone integrating directly.
Partners, partnerships, agreements and contributions (9 actions)
| Action | Reachable by | Note |
|---|---|---|
| Create a partner organisation | Nothing reaches it | The only way to create one anywhere in PTRS |
| Correct a partner organisation | Nothing reaches it | The only way to edit one, or turn it off |
| Read partner organisations | The Partnerships tab | Fills the partner dropdown on New Partnership |
| Create a partnership | The Partnerships tab | Its status is matched exactly, including case, see below |
| Read a program's partnerships | The Partnerships tab | Joined to the partner for its name; returns agreement and contribution counts |
| Create a partner agreement | Nothing reaches it | No screen creates one |
| Read a partnership's agreements | Nothing reaches it | No screen lists them |
| Record a contribution | Nothing reaches it | No screen records one |
| Read a partnership's contributions | Nothing reaches it | No screen lists them |
Creating and correcting a partner organisation both have a function and a hook ready to call them, and neither has any control anywhere that calls it.
The New Partnership dialog's only required field is a partner, chosen from a dropdown filled by reading partner organisations. In any organisation where none has been added directly, that list is empty, and pressing Create does nothing at all: no request, no error, no message.
So the partnerships feature is unusable from a cold start, and the four agreement and contribution actions behind it are unreachable twice over.
Who signed an agreement and when are both shown by the screen and have no writer anywhere in the solution. There is also no action that would correct an agreement, so its status is fixed at whatever creating it set.
A pending-signature status is therefore terminal: an agreement can be created awaiting a signature and can never actually be signed.
A contribution's value is optional and saved exactly as sent. Nothing sums it, not per partnership, not per program, not per organisation. The partnerships screen shows a count of contributions, never a value.
A partner's in-kind and financial contribution to a program is therefore recordable and not reportable, which is the figure a funder actually asks for.
Whether a value is matched with or without regard to case is inconsistent across this subset:
| Action | Matching |
|---|---|
| Setting a budget's line items, recording an expense | Without regard to case |
| Creating a partnership | Exact match, including case |
| Creating a partner agreement | Exact match, including case |
| Recording a contribution | Exact match, including case |
| Setting compliance requirements | Exact match, including case |
| Creating a program document | Exact match, including case |
The six exact matches all refuse a bad value by naming it, so the failure is clear, but someone integrating who sends lower-case values will succeed on a budget category and fail on a document type in the same sequence of requests.
Compliance requirements (2 actions)
| Action | Reachable by | Note |
|---|---|---|
| Set a program's compliance requirements | Nothing reaches it | Replace-all. The only way to record a program's DELACARE, OCCL or federal requirements |
| Read a program's compliance requirements | Nothing reaches it | The only way to read them |
The Compliance tab does not load any data from PTRS at all. Its requirements list is a fixed, empty value built into the screen, and it discards the program it is looking at without reading it.
The screen then works out a score from that empty list, which is always zero, and shows it in the red band, since the badge turns red below 60.
So every program in every organisation shows 0% Compliant in red, under the heading "Track DELACARE, OCCL, and federal compliance for this program".
This is a second compliance score in PTRS, worked out on the screen over a fixed, empty list. The first, the organisation-level one, cannot be worked out at all; see How the compliance score is calculated. One prints a passing verdict over zero checks and this one prints a failing verdict over zero checks. Neither has actually read anything.
The screen's own local fields do not match what PTRS would actually send back either, and one field the screen expects does not exist on the record at all, so wiring the page up as written would not fix it.
The screen's own colour map for requirement types has five entries. PTRS's own list has twelve. Four match; one screen entry names a category that is not real, and eight real categories have no colour assigned at all.
Program documents and versions (4 actions)
| Action | Reachable by | Note |
|---|---|---|
| Create a document record | The Documents tab | Sets the current version to 1 and marks it active, and writes no version history row |
| Read a program's documents | The Documents tab | Ordered by title |
| Add a document version | Wired up, never reached | The control is imported into the screen and no button calls it |
| Read a document's versions | The Documents tab | The version-history section, shown when a document is expanded |
- Creating a document writes no version-history row. It sets the current version number on the document and inserts nothing into the version history, so version 1 is never in it.
- Nothing can create version 2 either. The control that would is wired up and never called.
Version History therefore always shows "No version history", for every document. Were the button wired up, the history would start at version 2 and the original file would never appear in it.
Adding a version is otherwise correct: it does increase the current version number, save the new version with that number, and copy the file details onto the parent document.
The Document Type box is free text, and its placeholder suggests three examples. PTRS's own list has twelve members, matched exactly including case:
- Policy, parses.
- Compliance, not a member, refused.
- Form, not a member, refused.
- policy, refused, because the match does not ignore case.
- Blank, the screen substitutes Other, which parses.
So two of the three values the placeholder suggests are rejected, and the only reliably successful choice is to leave the box empty.
A document's active flag has no writer after creation, so the Archived counter is permanently zero.
Funding allocations (2 actions)
| Action | Reachable by | Note |
|---|---|---|
| Create a funding allocation | Nothing reaches it | Checks the program, the funding source and the grant if given |
| Read a program's funding allocations | Nothing reaches it | Ordered newest first |
Allocations are the join between a program and the money behind it, and there is no screen for them. The action itself is careful, refusing a missing program, funding source or grant by name, and no one can reach it.
Nothing compares an allocation with anything. The sum of a grant's allocations is never checked against the grant's own amount; the sum of a program's allocations is never checked against its own budget total. There is also no way to correct or remove one once created.
Pillars (1 action)
| Action | Reachable by | Note |
|---|---|---|
| Read the national program pillars | Nothing reaches it | Reference data, in a fixed order |
The national program pillars are the BGC national programme framework: Academic Success, Good Character and Citizenship, Healthy Lifestyles, Career Readiness, Arts and Culture, STEM.
The six pillars are only ever given to a copy of PTRS built for the development team, inside a block that only runs there.
So in an installed, live copy the pillar table is empty, and reading the pillars returns nothing. Two other places depend on that same table, so a program's pillar tags resolve to nothing there too.
This is the third table in PTRS whose only source is a development-only starting set, after CACFP's claim validation rules and meal pattern rule set. The pattern is worth naming: reference data that the product treats as configuration and the underlying code treats as a one-time fixture.
Reading the pillars is also reachable from no screen, so even in a development copy, nothing displays the list.
What this subset cannot do, in one table
| Capability the screens imply | Why it does not happen |
|---|---|
| Edit a charter | Reachable from no screen |
| Set a charter's effective or expiry date | Same action |
| Expire or supersede a charter | No writer for either stage; the expiry date is never compared with today |
| Approve a budget | Reachable from no screen |
| Allocate a budget across categories | Reachable from no screen; the allocated total is always zero |
| Approve or pay an expense | No writer for any status but Pending |
| Add a partner organisation | Reachable from no screen |
| Activate or end a partnership | No correcting action exists |
| Record or sign a partner agreement | Both reachable from no screen; who signed and when have no writer |
| Record a partner contribution | Reachable from no screen; and nothing sums the value |
| Record a program's compliance requirements | Both reachable from no screen; the tab calls nothing |
| Allocate funding to a program | Both reachable from no screen |
| Version a document | Wired up, never called; and the first version is never written |
| Archive a document | No writer after creation |
| See the national program pillars | Reachable from no screen, and the table is empty outside development |
Checked against PTRS on 7 September 2026.