Skip to content

Disbursements flow - #4987

Draft
bickelj wants to merge 18 commits into
mainfrom
disbursements-flow
Draft

bickelj wants to merge 18 commits into
mainfrom
disbursements-flow

Conversation

@bickelj

@bickelj bickelj commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Note: this is a draft, not ready for merge by any stretch of the imagination (I don't expect lint or tests to even pass yet). I cherry-picked the relevant commits into a first-pass on main here while the commit order was top of mind. There will be more commits added as the feature evolves downstream.

Without this change, there is quite a complex process for invoicing, approvals, and tracking of payments. With this change, there is a relatively straightforward way to associate money amounts with contracts and then disbursements with those contracts. It breaks the 1-to-1 project-to-contract relationship when a system setting PROJECTS_PAYMENTS_FLOW is set to DISBURSEMENTS. The standard flow is INVOICING and another is offered: DISABLED. The same Contract model is re-used in either flow, but after that, the models/forms/views diverge.

"BRL",
"MXN",
"NGN",
]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a setting. The values seem good as a default.

@bickelj
bickelj force-pushed the disbursements-flow branch 2 times, most recently from 8ecc136 to d7bc9a8 Compare November 4, 2026 21:40
bickelj and others added 4 commits November 5, 2026 13:06
A broad range is allowed so as to support current and future monies.
Several fiat currencies use 0 or 3 decimal places. Several digital
currencies support 6-18 digits following the decimal place. Displaying
the amounts in a sensible way will be a UI concern.

Thanks to GLM-5.2 (LLM) for helpful hints.
Offer an hint at currency codes with a datalist with top ten codes.

Actually load original when editing and save updates to the contract.

There is wide decimal precision available on input, but exactly two
decimal places are shown in the UI unless more are used.

LLM assistance by unsloth/Qwen3.6-35B-A3B-GGUF:UD-Q4_K_XL
Further LLM assistance by GLM-5.2
Introduce a Disbursement model (one transaction against a Contract)
recorded by staff with no approval workflow. Negative amounts are
allowed so repayments net out via Sum(). The canonical audit trail is
written to Wagtail's ModelLogEntry via wagtail.log_actions.log on every
save, mirroring ApplicationRevision.save; activity/messenger notices
are a separate, best-effort concern for the views MR.

This is model-only: CRUD views, the All Projects columns, and the
audit report come on a follow-on branch.

GLM-5.2
Stack create/update/delete views (staff/finance), a DisbursementForm,
and URL routes on the Disbursement model. Entry is a modal on the
project page; on save the user returns to the project page.
Activity/messenger notices are emitted for create/update/delete with
the amount included (not the note), wired through the activity
adapters like invoices.

GLM-5.2
@bickelj
bickelj force-pushed the disbursements-flow branch 2 times, most recently from 40d5b66 to db0136d Compare November 5, 2026 19:55
bickelj-agent and others added 14 commits November 6, 2026 10:00
Render a "Contracts and Disbursements" section where upstream places
invoices: it lists each contract (with its approved amount) and its
disbursements, with Add/Edit/Delete disbursement buttons gated by the
can_add_disbursement checker (staff/finance/contracting). Staff/finance
can also add further contracts from here, reusing the countersigned
contract form (no stage transition; the first contract still goes
through the contracting flow, which transitions the project). Notes
are staff/finance-only, so the Notes column is omitted for applicants.
Amounts display with a minimum of two decimal places, keeping any
extra precision, to match the contract amount rendering.

GLM-5.2
The ARDC fork needs a per-contract disbursement ledger in place of
upstream's invoicing flow, but unconditionally removing the invoicing
UI would break other deployments sharing this fork base. Add
PROJECTS_PAYMENTS_FLOW (an INVOICING/DISBURSEMENTS/DISABLED enum) so
each deployment selects its payments flow. The project detail page
renders each section through a helper tag (project_can_have_invoices_
section / project_can_have_disbursements_section) that folds the
payments-flow check in with the existing visibility rules, keeping
the template terse; the contracting documents section stays during
Contracting and is hidden under DISBURSEMENTS once a contract exists
(the C&D section takes over). The contract upload forms
(UploadContractForm, UploadCountersignedContractForm, and the
CreateContractForm that extends it) likewise hide their
amount_requested, amount_approved and currency fields unless
DISBURSEMENTS is selected, so the ledger fields only appear where
the per-contract ledger exists. ARDC sets DISBURSEMENTS in ardc.py.

GLM-5.2
Without this change, the currency code input widget was the same size
in appearance as the amounts. With this change, its size and maximum
length are proportioned more accurately.
For convenience, use the system setting's `CURRENCY_CODE` to
prepopulate the currency field on a contract. It can still be left
blank for several reasons: it may not be known yet and it is still
important for old, existing data to allow `NULL`, also when not using
the `PROJECTS_PAYMENTS_FLOW=DISBURSEMENTS` setting it will be `NULL`.
Without this change, it is hard to tell what currency is disbursed.
With this change, it is easier because the contract's currency shows.
The disbursements table had no horizontal scroll wrapper. Its nowrap
thead gives it a ~707px minimum width, so on narrower viewports the
table and its Edit/Delete buttons rendered outside the card border.

Now the table scrolls within the card, as the sibling invoice and
report tables already do.

Made with GLM-5.3-Flash.
Without this change, the Disbursement form's Amount label does not
say which currency the entered amount is in. With this change, the
related Contract's currency code shows next to the Amount label,
matching the Disbursements table header.

Assisted-by: GLM-5.3-Flash
In most currencies we use two decimal places and right-justify amounts
so this change does the same for the Disbursements table that shows up
in the Projects area.
Staff previously keyed each disbursement amount from scratch. The
create form now starts from the awarded amount net of the
contract's existing disbursements, and editing keeps the amount.

GLM-5.3-Flash, an LLM supervised and prompted by @jbickel
The Notes column in the Contracts and Disbursements section was
hidden from applicants and labelled "visible to staff and finance
only", so grantees could not see the notes staff record against
their disbursements.

Now anyone who can view the project sees the Notes column and its
contents; recording and editing disbursements stay staff/finance.

GLM-5.3-Flash, an LLM supervised and prompted by @jbickel
Disbursements were only visible per project, with no way to see or
extract money movement across all projects. Add an admin-only ledger
at /apply/projects/disbursements/ (Staff Admin group or superuser):
one row per disbursement with contract requested/approved amounts
repeated, ISO 8601 disbursement-date and date-recorded columns,
date-range, currency and project-status filters, a numeric total when
a single currency is filtered, and filter-respecting CSV export. The
nav entry and page only exist under the DISBURSEMENTS payments flow.

GLM-5.3-Flash, an LLM supervised and prompted by @jbickel
The per-contract Disbursements section gave weak labels: the
contract link read just "#65", the disbursement list had no heading,
and the first column said "Date".

The contract link now reads "Contract #65", the list carries an
"N Disbursements:" count heading under each contract, and the first
column is "Disbursement date", matching the All Disbursements table.

GLM-5.3-Flash, an LLM supervised and prompted by @jbickel
Staff had to open each project to see its contract totals. The All
Projects table now shows a contracts total per project with its
currency code, and shows "Multiple currencies" instead of a
cross-currency sum when the amounts span more than one currency.
Projects with no approved amount entered show an em dash rather than
0.00, keeping absence distinct from a genuine zero. The column is
gated on the DISBURSEMENTS payments flow, where contracts carry
amounts at all.

GLM-5.3-Flash, an LLM supervised and prompted by @jbickel
Staff tracking grant money had to open each project and read
through its contracts and disbursements to learn how much had
gone out. The All Projects list and its CSV export now show each
project's disbursement total, summed across all of its contracts,
with repayments netting out. Totals spanning more than one
currency, including a coded amount beside an uncoded one, show as
"Multiple currencies" instead of a blended amount; a single
currency code is shown beside the total. Projects without
disbursements show "—" rather than a misleading 0.00.

GLM-5.3-Flash, an LLM supervised and prompted by @jbickel
@bickelj
bickelj force-pushed the disbursements-flow branch from db0136d to 619c8b2 Compare November 6, 2026 16:13

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants