5. Granted

All roles can readFinance/Admin can edit budgets + push to OdooProgramme can refresh actuals + manage projects

Awarded applications become Grants. This is the screen finance officers spend most of their time on.

The grant detail page

Long vertical page with several cards:

Header

  • Grant title, reference (auto-generated), donor name, cycle name.
  • Status pill (Awarded / Active / Closed).
  • Grant amount, period, currency, contract number.
  • "Edit grant" button (Finance/Admin only) for amount, currency, dates, contract number.

Projects card

One row per executing project. Each row shows its Odoo sync status (Synced / Sub-grant Draft / Sub-grant Started / Pending / Failed). Click "+ Add project" to create one — this lands the project in Odoo unless you mark it as "not in Odoo" (used for sub-grant partners that book elsewhere).

The Add / Edit modal asks for:

  • Project name.
  • Organizational units — the implementing organizational unit. Default for the Odoo company.
  • Odoo company (optional override, F2-B+) — pick a different res.company than the organizational unit's default. Use only for joint-implementation cases where the booking entity and the executing organizational unit differ. Leave on the default in the typical case.
  • Analytic code[COUNTRY3]-[DONOR3]-[GRANT3] format. Used as the project's Plan 1 analytic account code in Odoo.
One project = one Odoo company. Cross-administration projects aren't supported — that pattern fits better as several sub-grants under one Grant, each in its own administration. Standard practice across EU INTPA, USAID, NL MFA and UN agency reporting.
Draft vs Started for sub-grants. Sub-grant projects (not_in_odoo) don't have an Odoo lifecycle to lean on, so the status is inferred from manual actuals: any entry > 0 ⇒ Started, else Draft. Visible on both the Projects list and the project detail page.

What it looks like

PROJECTS & ANALYTIC
Project Organizational unit Analytic code Odoo project Status
Acme Ethiopia — Civic Voices programme Acme Ethiopia ETH ETH-EUX-CVP #3 ● Synced  
Local partner — capacity building Acme Ethiopia ETH ETH-EUX-CAP ● Sub-grant · Started  
Add project Clicking Create in Odoo creates the analytic accounts and the project in your organization's Odoo. Re-clicking a synced row is a no-op.

Illustration only — your projects card will list every project on this grant with the exact same column structure.

Granted budget card

The donor-facing budget for this grant — locked when the contract was signed, labelled Granted budget in the UI (the pre-award equivalent on the application page is called Application budget). One row per category defined on the cycle template (see chapter 12.3). Each row carries:

  • Description — optional note shown to the donor.
  • Budget amount — what you committed to the donor. Either a manual amount (when the cycle has no detail template) or a computed SUM of detail rows (when it does).
  • Allocated — total of per-project allocations for this line. Difference column highlights gaps.
  • Odoo column — Plan 2 analytic account reference + a "● synced" tag once the line is pushed to Odoo.

When the cycle has a detail template, each category expands into detail rows (Country Director, International travel, etc.). You can edit units × value inline, add new rows per category, or remove rows. The SUM rolls up live to the category.

What it looks like

Granted budget Hide details Linked to Odoo budget #2

The donor-facing budget for this grant. Each line maps to one of the six shared analytic accounts in Odoo (HR · TRV · EQP · OFF · SVC · IND). Currency: EUR.

Budget line Description Budget Allocated Difference Odoo
HR
Human Resources
Human Resources 471.415 20.000 € 451.415 HR● synced #7
Detail (11) · derived from cycle template
1.1.1.a Country Director (40%) 36 x 2.675 / month € 96.300
1.1.1.b Programme manager (100%) 36 x 3.140 / month € 113.040
… 9 more HR detail rows in the live grant — Project officer, Finance manager, Per diems, Seminar costs … …
TRV
Travel
Travel 134.616 20.000 € 114.616 TRV● synced #8
IND
Indirect costs
7 % of direct subtotal 42.430 0 € 42.430 IND● synced #12
Grant total € 648.461 € 40.000 € 608.461
Save Save & sync to Odoo Refresh actuals Last actuals refresh: 2026-05-22 14:31

Illustration only — rendered with the real design-system classes so it stays in step as the app evolves. The live screen shows all 27 detail rows under HR and all six categories; the IND row carries a dashed border on the Budget cell to signal it's a computed value, not directly editable.

Indirect rows. If a category is marked % of direct in the cycle, its units field holds the percentage (e.g. 7 for 7%), and the amount auto-computes as (units / 100) × direct subtotal. The value column is unused.

Multi-year budgets (F12-B)

Grants that run longer than one fiscal year — typical for EU and UN programmes spanning two to five years — can split their Granted budget across years. The Edit grant modal carries a Budget years field (1 – 7) that controls the shape:

  • Budget years = 1 (the default). One row per cost category, exactly the layout described above. Today's behaviour, unchanged.
  • Budget years ≥ 2. Each cost category gets one row per fiscal year under the hood. The Granted budget card switches to a year-columns layout: HR · 2027 · 2028 · 2029 · Total · Allocated · Diff. Sub-totals + grand total sit at the bottom; allocations sum across years.

Year numbering derives from the grant's start_date: a grant starting 2027-01-15 with budget_years = 3 renders 2027 / 2028 / 2029. NIMD's Jan – Dec fiscal year matches this exactly; tenants on a non-January fiscal calendar can layer a label override later — the underlying integer stays a calendar year so cross-tenant aggregation stays simple.

What it looks like

Granted budget Multi-year · 3 yrs Linked to Odoo budget #2

The donor-facing budget for this grant, split across 3 fiscal years (2026 – 2028). Each year is its own budget_lines row, so reallocations + Odoo analytic syncs stay per-year. Currency: EUR.

Edit: All years (summary) 2026 2027 2028
Cost category 2026 2027 2028 Total Allocated Diff
HR
Human Resources
€ 471.415 € 500.000 € 971.415 € 971.415
TRV
Travel
€ 134.616 € 134.616 € 134.616
EQP
Equipment
€ 11.200 € 11.200 € 11.200
SVC
Other costs & services
€ 1.125.446 € 1.125.446 € 1.125.446
IND
Indirect costs
€ 126.879 € 126.879 € 126.879
Total grant budget € 1.939.432 € 500.000 € 0 € 2.439.432 € 0 € 2.439.432

Illustration only — rendered with the real design-system classes so it stays in step as the app evolves. Click 2026 / 2027 / 2028 on the live screen to drop into the single-year editor for that year.

Editing each year

A year-tabs strip lives above the budget on multi-year grants: [All years (summary)] [2027] [2028] [2029]. The default All years tab renders the read-only year-columns summary above. Clicking a specific year opens the familiar single-year editor — same per-detail / per-allocation UX as today, just scoped to that year's budget_lines rows. Every save fires a normal Budget saved. redirect and the totals on the summary tab update on next render.

Reallocations work per-year automatically because each year is its own budget_lines row: the F11-D log entries carry the affected year alongside the scope tag, so a donor can see "we moved €5k inside Tanzania's HR in year 2" without sniffing for context.

EU Annex III export

The donor XLSX gains one Year YYYY sheet per fiscal year, slotted between the Direct sheet and Partners. Each year-sheet uses the same layout as Direct but filtered to that year's rows. Single-year grants are bit-for-bit identical to before — no surprise extra tabs.

Toggling between 1 and ≥ 2

Bumping a single-year grant up to multi-year is non-destructive: the existing amounts + detail rows + allocations stay attached to year 1, and the additional year-rows start empty so you can fill them in.

Going back down (e.g. 3 → 1) is also non-destructive — but the orphaned year-2..N rows stay in the database in case you flip back. The single-year render hides them, showing each category exactly once with its year-1 data. Re-enabling multi-year restores the saved year-2..N amounts.

When to use which. Donors who report annually (EU Annex III, USAID, UN agencies, BMZ) almost always want year columns — use multi-year. Donors with a single end-of-grant report (some private foundations) can stay on single-year. Up to seven years is enforced at the schema level; longer than that, talk to us first.

Reallocations & locks

When the donor signs the contract, togrant captures a baseline snapshot of the budget at that moment. A teal banner appears at the top of the grant page (Approved baseline locked · YYYY-MM-DD · by [name]) and every subsequent budget edit is logged as a reallocation.

  • When you save changes to a locked budget, a justification modal opens showing exactly which lines changed (old → new, with the delta). The reason textarea is labelled (recommended) — the audit row is written either way, but a narrative makes the eventual donor addendum readable without going back to memory. You can choose:
    • Cancel — close the modal, no save.
    • Save without note — save the edits and log them as reallocations, but leave the reason field empty. Useful for corrections and currency revaluations where there's no narrative.
    • Save & log — save with the typed reason. The narrative shows up verbatim in the donor addendum export (chapter 5: Donor reports).
  • A new Reallocations card on the grant detail lists every logged change since the baseline: date, who, scope (category / detail row), was → now, the delta, and the reason. The top of the card summarises the net delta per category as colored chips (+€X in green, -€Y in amber) so you can see at a glance where the money has moved.
  • Once at least one reallocation exists, a ↓ Generate addendum (XLSX) button appears in the card header. Click it to download a two-sheet workbook: Budget (per-category original / Δ / revised columns, donor-formatted) and Justifications (chronological narrative of every shift with actor + date + reason). The format is generic — EU centralised grants get the Annex III header, Dutch MFA grants get a NL bijlage header, other donors get a clean neutral template. Edit the file before sending if your donor wants a specific layout.
  • Older grants created before the lock mechanism shipped get an amber "Draft baseline" banner instead. Their edits aren't tracked. A superadmin can manually lock them when needed.
  • Per-project funding agreement. Once the grant is locked, each project page shows a Sign funding agreement button. Click it after the internal HQ → country office (or HQ → partner) agreement is signed — the project's current budget allocation becomes its own locked baseline, separate from the grant-level audit log. Subsequent edits on that project's detail rows and category-level allocations are logged with lock_level = 'project'. Works for both Odoo-synced and sub-grant (not_in_odoo) projects — the snapshot captures category-level allocations alongside any detail rows, so a sub-grant whose budget lives only at the category level still gets a proper audit trail. Useful for multi-country grants where each country office's funding agreement gets signed at a different moment.
  • Donor addendums. When the donor signs a formal budget revision, open the Donor addenda card on the grant detail and click ↑ Upload addendum. The modal captures the signed date, an addendum reference (e.g. FED/2022/438-911 Add. 1), optional internal notes, and the signed PDF. On save togrant snapshots the current budget state as the new locked baseline and marks every reallocation logged so far as absorbed by this addendum — so the Reallocations card resets to track changes against the new baseline, while the historical entries stay visible in the addendum XLSX export. Useful when the donor approves a year-end budget revision and you want a clean slate going forward.
  • Edit grant modal — once the baseline is locked, the Amount, Currency and Donor fields render as read-only chips. They are part of the donor-signed contract; changing them requires a formal addendum (not yet built in togrant — coming with the addendum upload flow). Title, dates, contract number and short code stay editable as administrative metadata.
Why the modal asks for a reason. Most donors (EU, Dutch MFA, USAID, FCDO) require formal justification of every budget shift greater than a threshold. By documenting the change at the moment of editing, you build the addendum table while you work instead of reconstructing it at year-end from emails and meeting notes.

Budget vs Actual card

Per category: Budget, Actual (from Odoo + manual sub-grant entries), Remaining, % spent with a progress bar. Color codes: teal < 85%, amber 85–100%, red > 100%.

What it looks like

Budget vs Actual Last refreshed 2026-05-22 19:52
Budget line Budget Actuals Remaining Spend
HR
Human Resources
€ 471.557 € 0 € 471.557
0%
TRV
Travel
€ 134.613 € 0 € 134.613
0%
EQP
Equipment
€ 11.200 € 0 € 11.200
0%
OFF
Project Office
€ 69.878 € 0 € 69.878
0%
SVC
Other costs & services
€ 1.125.105 € 3.314 € 1.121.791
0.3%
Subtotal direct € 1.812.354 € 3.314 € 1.809.040
0%
IND
Indirect costs (7%)
€ 126.865 € 0 € 126.865
0%
Total project € 1.939.218 € 3.314 € 1.935.904
0%
Refresh actuals from Odoo

Illustration only — the Spend bar turns amber at 85–100% and red above 100%, so overspends jump out at a glance.

Action buttons (Finance/Admin)

  • Save — persist budget edits.
  • Save & sync to Odoo — persist + push the budget to Odoo. Creates Plan 2 + Plan 3 analytic accounts and writes per-project budget rows at both category and detail granularity.
  • Refresh actuals — pull analytic lines from Odoo and update the Actual column. Per-detail amounts populate budget_detail_lines per project (visible on each project detail page and aggregated on the grant's EU export).
Per-project detail budgets (F10). Each project keeps its OWN snapshot of detail rows — no more proportional split. On first open of a project page the grant's template rows are copied as project-scoped rows; you then edit units × value per project independently. Save & sync emits one Odoo budget.line per category and one per detail row, each carrying exactly the amount you typed on the project page.