Skip to content

Disbursements flow - #4987

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

bickelj wants to merge 6 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.

bickelj and others added 6 commits September 11, 2026 10:32
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
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
"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.

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