7. Reporting

All roles can readProgramme/Finance/Admin can refreshFinance/Admin can export

One page per grant with a period selector, KPI tiles, the contract summary, and an EU donor XLSX export.

Period selector

Dropdown of generated periods: Cumulative + Year 1/2/3 + (mid-term) + Final + calendar/fiscal years. Periods come from the cycle's reporting cadence (chapter 12.5) when one is configured, otherwise from the default generator.

Switching periods filters every number on the page to that date window. The export uses the same selection.

KPI strip

  • Budget — total committed in the selected period.
  • Actuals — sum of postings (Odoo + manual sub-grant) in the period.
  • Spent — % of budget consumed.
  • Remaining — budget − actuals.

Per-category table

One row per cycle category. Direct subtotal + indirect rows separated for clarity. The Difference column highlights overspend. On a multi-year grant the categories are summed across all fiscal years, so each category appears once (not once per year).

Open in Odoo

Next to the Refresh button on the Budget vs actuals card sits a blue Open in Odoo link — one per project that is synced to Odoo. It opens that project's Analytic Items list in Odoo in a new tab, already grouped by budget category, so you can drill from a reported figure straight into the underlying postings.

Why it lands on the project, not a single category. Odoo 19's web router drops URL filters from deep links, so togrant can't pre-filter the Analytic Items list to one category or fiscal year from the outside. The project-scoped view — grouped by category in Odoo itself — is as deep as a link can reach. From there, one click on a category or period group narrows it further inside Odoo.

Detail breakdown card

Expandable card showing every detail row with its budget, actual, and variance — populated from budget_detail_lines after a Refresh actuals.

Reporting currency & exchange rates

The grant's currency is its reporting currency: the budget is authored in it, all actuals are converted into it, and the export is denominated in it. That works out of the box while every posting is booked in the same currency (the common case). It matters the moment a grant spans multiple country offices whose Odoo companies keep their books in different currencies — Odoo stores each analytic line in the booking company's own currency, so summing them raw would silently mix currencies.

A Reporting currency & exchange rates card on the grant page (finance/admin only) handles this. togrant auto-detects every foreign currency that appears in the grant's postings and lists one row per currency:

  • Fixed — one donor-agreed rate for the whole grant, entered by hand. This is the donor default: EU INTPA, the Dutch MFA and most institutional donors require the report at an agreed rate, not the daily market rate. The card states the direction explicitly (1 UGX = 0.00024 EUR) and shows the inverse read-only so the rate can't be entered upside-down. Store the donor agreement reference in the note field.
  • Odoo — convert at Odoo's own dated rate per posting (via res.currency), for grants whose donor accepts Odoo's rates. No rate to type.

Conversion happens per line, then sums — each posting is converted and rounded to the reporting currency before it's added up, so the category total always equals the sum of its converted transactions (see the Transactions sheet below). What togrant caches in the actuals is therefore already in the reporting currency, keeping budget-vs-actual apples-to-apples.

Rate required. A foreign currency with no rate configured is excluded from the converted actuals — never silently guessed — and the card shows an amber "N currencies awaiting an exchange rate" banner. A Refresh actuals that skips lines for this reason also flags it, and the skip is recorded in the sync log. Set the rate, then Refresh actuals to restamp the cached figures. (Changing an existing fixed rate likewise needs a re-refresh.)

What it looks like

Reporting currency & exchange rates Reporting in EUR

The budget and all actuals are reported in EUR. Postings booked in another currency are converted using the rates below.

CurrencyModeRate (1 unit = ? EUR)Note
ETB Fixed rate 0.016 Donor agreement §7
UGX Fixed rate 0.00024 EU FED/2022 Art. 4.2
Save rates Fixed = one agreed rate for the grant. Odoo = the administration's dated rate. Re-run "Refresh actuals" after changing a rate.

Above: an Ethiopia office booking in ETB and a Uganda office in UGX, both fixed at the donor-agreed rate. A currency with an empty rate would instead show the amber "rate required" banner and be held out of the actuals.

The budget itself is always in the reporting currency — foreign-currency budgets (as opposed to actuals) are out of scope; only the actuals coming back from Odoo are converted.

EU donor XLSX export

Generates the EU consolidated financial report layout (multi-sheet workbook):

  • Budget vs Actual main sheet — categories + detail rows, populated.
  • Year YYYY sheets (only when the grant has Budget years > 1; see chapter 5 Multi-year budgets). One sheet per fiscal year between the main sheet and Partners, filtered to that year's budget_lines rows. Same layout as the main sheet so reviewers don't have to relearn the columns.
  • Partners sheet — split of actuals per sub-grant partner (from manual actuals on not-in-Odoo projects).
  • All Report sheet — wide layout with calendar/fiscal year columns.
  • Transactions sheet — every individual Odoo posting line behind the report (only when there are Odoo-synced projects). Columns: Date · Description · Project · Category · Detail · Currency · Amount · Amount (reporting). It gives the donor a line-by-line audit trail, and it reconciles: the sum of the Amount (reporting) column equals the category actuals on the main sheet. When a foreign currency is in play (see Reporting currency & exchange rates), each line shows its original currency and amount next to the converted figure.

The selected period drives the date filter. Cumulative gives the standard donor-format export; pick Year 1/2/3 for annual reports. On a multi-year grant the per-year sheets give you the same split without re-running the export.

Transactions sheet — what it looks like

Transactions Reporting currency: EUR
DateDescriptionProjectCategoryDetailCurrencyAmountAmount (reporting)
2025-03-14 Field coordinator salary Ethiopia office HR HR-01 Staff ETB 45.000,00 € 720,00
2025-04-02 Kampala workshop venue Uganda office SVC SVC-02 Events UGX 3.800.000,00 € 912,00
2025-04-20 Consultant fee HQ SVC SVC-01 Consultancy EUR 3.314,00 € 3.314,00
Total (reporting) € 4.946,00

Each line keeps its original currency and amount next to the converted figure. The Amount (reporting) column sums to the category actuals on the main sheet — here ETB 45.000 × 0.016 and UGX 3.800.000 × 0.00024 land as € 720 and € 912, the EUR line passes through unchanged.