Acumatica · Reports

Acumatica Cash Flow Report — Tuning Guide

Acumatica Cash Flow Report — Tuning Guide is one of those reports every business needs and almost no business has a clean implementation of.

John Kihiu12 min read

A cash flow report — whether it's a simple projected-cash statement or a full indirect-method statement of cash flows — has a bottleneck that doesn't show up in the other financial reports: it has to blend actual posted transactions with unposted, expected, and recurring items, from three different subledgers, on three different timelines. That blending, not the SQL volume, is what makes cash flow reports slow and fragile to build.

Three different notions of "when"

A projected cash flow report typically needs: AP bills not yet due (future outflow, known amount, known date), AR invoices not yet collected (future inflow, known amount, estimated date based on terms or historical days-to-pay), and recurring/scheduled transactions (payroll runs, loan payments) that may not exist as documents yet at all — they're generated by a schedule. The first two are joins against real tables with real filter predicates. The third is not queryable the normal way; if the report needs to show next month's payroll before it's been processed, you either materialize projected transactions into a staging table ahead of the report run, or you accept the report only shows what's already posted or scheduled as a document.

Decide projected vs actual before you touch the schema

The single biggest scope mistake I see on cash flow report requests: the client says "cash flow report" meaning a forward-looking projection, and the build starts from the GL's actual cash account activity, which is inherently backward-looking. Nail down which one is being asked for in the kickoff conversation — they are different data sources and different reports, not one report with a toggle.

The indirect-method statement: reclassifying GL activity, not summing it

If what's needed is the accounting statement of cash flows (indirect method — net income adjusted for non-cash items and working-capital changes), the report is walking GL activity and re-bucketing it into operating/investing/financing categories based on account mapping, not summing a single account. That means a mapping table (which GL accounts or account groups map to which cash flow category) has to exist and be joined against — usually a custom mapping DAC, since Acumatica doesn't ship one out of the box for this purpose. Build that mapping once, as a maintainable table an accountant can edit, rather than hardcoding account ranges into report filter expressions that only a developer can update.

SCHEMA — GL ACTIVITY JOINED TO A CASH-FLOW CATEGORY MAP
Base:  GLTran WHERE FinPeriodID BETWEEN @FromPeriod AND @ToPeriod
Join:  KGCashFlowCategoryMap ON AccountID = KGCashFlowCategoryMap.AccountID
Group: by KGCashFlowCategoryMap.Category, FinPeriodID

Filtering GL activity by FinPeriodID rather than transaction date is worth repeating here specifically because cash flow reports are almost always run period-over-period (this month vs last, this quarter vs last), and FinPeriodID is the indexed, string-sortable field Acumatica's own balance tables are built around — date-range filtering on a large GLTran table for a multi-period comparison is measurably worse.

Wrapping up

Cash flow reports are slow because they're doing conceptual work, not just data volume work: blending three timelines for a projection, or reclassifying GL activity through a category map for a statement. Get the projection-vs-statement scope nailed down first, build a real editable mapping table for the indirect method rather than hardcoded account ranges, and filter GL activity by financial period, not date, for anything period-over-period.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.