Skip to main content
iVentureTeam

analytic_distribution

The field that splits a journal item across analytic accounts by percentage is one widget: analytic_distribution. Eight options, a tag-based editor, and a type change in 19 worth knowing about.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 11, 2026Updated August 11, 20266 min read
Odoo 19 journal item line showing the analytic_distribution widget with analytic accounts as percentage tags and the distribution editor dropdown open.
Technical nameanalytic_distribution
Field typesjson
Viewsform, list (journal items, expenses, order lines)
Moduleanalytic, installed with Accounting, Projects and other analytic users
Used in core22 occurrences across 7 modules, including account, analytic, hr_expense, purchase, l10n_account_withholding_tax, sale
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0, Odoo 16.0
No-code setupNo. The widget is placed in view XML; the analytic plans and distribution models it uses are configured in Accounting settings without code
Alternativesmany2many_tags, percentage, Separate analytic account fields (pre-16 pattern)

What the Analytic Distribution field does

Analytic accounting answers the question financial accounts cannot: not just how much was spent, but on which project, department or cost center. The analytic_distribution widget is the entry point for that data. On a journal item, an expense line or a purchase order line, it shows the current split as compact tags, each an analytic account with its percentage, and clicking in opens a dropdown editor where the user distributes the line across accounts, one column per applicable analytic plan.

It is one of the largest field widgets in Odoo, around 750 lines in the 19.0 source, because it is really a small application: it loads the applicable plans, validates percentages against the fetched precision, positions its editor like a popover, and knows how to read neighboring fields on the record to suggest the right split.

The underlying field is JSON. That is also the widget's declared supported type in 19, a change from 18, where the same widget declared char and text.

What this means for your team

Cost visibility per project or department is one of the top three reasons companies implement Odoo Accounting, and this widget is where that visibility is won or lost. If entering the split is slow, people skip it, and every report downstream shows an Unallocated bucket nobody can explain at quarter close.

Two configuration decisions drive adoption. First, distribution models: recurring splits, rent 60/40 across two departments for example, should be saved as templates so the widget applies them automatically, and users only touch the exceptions. The widget supports creating those templates from the editor itself. Second, mandatory plans: applicability rules decide whether a missing split blocks posting or passes silently, and the widget's force_applicability option can tighten that per view.

Our rule from accounting implementations: make the split automatic for 90 percent of lines via models and defaults, and the remaining 10 percent will actually get filled by hand.

Supported options in Odoo 19

Verified against analytic_distribution.js in the Odoo 19.0 analytic module: eight declared options, plus one input that travels as an XML attribute rather than an option. The help texts below are ours; the source declares these options without help strings.

OptionTypeWhat it does
disable_savebooleanSwitches the widget's own save behavior off; the source inverts it into an internal allow_save flag. Used where the surrounding flow, a wizard for instance, owns persistence.
multi_editbooleanEnables list multi-edit behavior, applying one distribution to every selected line in a single edit.
force_applicabilitystring (declared boolean)Declared boolean in the options metadata, but the prop is typed string and passed through as-is, overriding how plan applicability is considered for this field. The implementation wins over the declaration.
business_domainstringBusiness context string passed into the widget's account lookup logic, letting the same field behave per document family. Its attribute-based sibling business_domain_compute is separate; see the deep dive.
product_fieldfield name (many2one)Field on the current record holding the product, part of the context the widget reads for distribution suggestions.
amount_fieldfield name (monetary)Field on the current record holding the line amount the distribution applies to.
account_fieldfield name (many2one)Field on the current record holding the financial account, the third piece of matching context.
placeholder_fieldfield name (char)Char field on the record supplying a dynamic placeholder while the distribution is empty. New in 19; the option does not exist in the 18.0 source.

One quirk read from the source: force_applicability is declared as a boolean in the options metadata, but the component types the prop as a string and passes the option value through untouched. Treat it as a string-valued setting aligned with analytic applicability values, and test what you pass; the declaration and the implementation disagree, and the implementation wins.

Working examples

Standard usage on a line model

<field name="analytic_distribution" widget="analytic_distribution"/>

Renders the tags plus editor against all applicable analytic plans.

Wiring the record context for better suggestions

<field name="analytic_distribution"
       widget="analytic_distribution"
       options="{'product_field': 'product_id', 'account_field': 'account_id', 'amount_field': 'price_subtotal'}"/>

Points the widget at the line's product, financial account and amount, the mapping core uses on journal items so distribution model matching sees the right context.

List view with multi-edit, without instant saving

<field name="analytic_distribution"
       widget="analytic_distribution"
       options="{'multi_edit': True, 'disable_save': True}"/>

multi_edit lets a selection of lines take the same split in one edit; disable_save switches the widget's own save behavior off so the surrounding flow stays in charge.

Precision, create-only templates, and the attribute in disguise

Details from the source that shape real implementations.

The precision comes with the field. The widget declares analytic_precision as a fieldDependency, so it is fetched automatically for every record, and percentage rounding runs through the shared rounding helper against it. If splits keep rounding to whole percents, that precision setting, not the widget, is what to change.

Templates are create-only from the widget. The editor's save-as-model path opens account.analytic.distribution.model with create and write enabled but edit disabled, meaning users can capture the current split as a new template but never land in an existing template's form from here. Managing existing models happens in Accounting configuration.

An attribute hides among the options. extractProps reads business_domain_compute from the element's attributes, alongside the business_domain option. If you set it as an option it does nothing, one more reason copying core view XML beats reconstructing it from memory.

The editor manages its own closing. Clicks inside popovers and active modals do not close it, a window resize closes it on desktop but deliberately not on mobile, and the whole thing repositions through the standard positioning hook. Worth knowing before you file a cannot-reproduce UI bug.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. The development branch keeps the entire option surface unchanged; internals rebuilt. See below.
Odoo 19.0VerifiedAll eight options verified against the shipped source. Declared type is json.
Odoo 18.0Partial / changedSame widget, but declared types are char and text, no placeholder_field option, and a company_id dependency that 19 dropped.
Odoo 17.0VerifiedWidget present with the same registry name. Not re-verified line by line for this page.
Odoo 16.0VerifiedWidget present with the same registry name, introduced with the analytic plans redesign. Not re-verified line by line for this page.

Upgrade note for 18 to 19. Two mechanical changes, both verified: the declared field type moved from char and text to json, and the company_id fieldDependency was dropped while placeholder_field was added to the options. Standard views migrate untouched, but custom models mirroring the 18 declaration and JavaScript patches around the widget deserve a check during an Odoo migration.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. We diffed this widget against the public development branch at the time of writing; the branch is unstable until feature freeze, and we re-verify after release.

The option surface is untouched: all eight options, the json type, the analytic_precision dependency and the extractProps mapping are byte-for-byte identical to 19. The internals are not: the tag rendering moves to a new badge component, an offline-handling plugin appears, and the component migrates to the new Owl syntax. In short, XML views carry into 20 unchanged on current evidence, while JavaScript patches against the component internals will need rework.

Common problems and fixes

SymptomCause and fix
Percentages keep rounding to whole numbersThe analytic precision fetched through the widget's field dependency is set low. Raise the percentage decimal precision in Accounting settings.
A plan column is missing from the editorThe plan's applicability rules exclude this document context. Review plan applicability in Accounting configuration, or set force_applicability on the field.
Users cannot edit an existing distribution model from the lineBy design: the widget opens templates create-only, with in-place editing disabled in the source. Manage existing models under Accounting configuration instead.
business_domain_compute set as an option does nothingIt is an XML attribute, not an option; extractProps reads it from attrs. Move it onto the field element as an attribute.
Suggestions ignore the line's product or accountThe mapping options are not wired, so the widget cannot see that context. Set product_field, account_field and amount_field as in the example.
Custom model's distribution field broke moving 18 to 19The widget's declared type changed from char and text to json. Store the distribution in a Json field, matching core's account.move.line.

Analytic Distribution field vs the alternatives

WidgetBest forKey difference
analytic_distributionSplitting journal items, expenses and order lines across analytic accountsPercentage tags plus a plan-aware editor on a json field; the only core UI for analytic distributions
many2many_tagsTagging lines with analytic-like labels without percentagesPlain relation, no splits, no plan logic
percentageA single stored percentage with no accounts involvedFormats one number; carries no distribution semantics
Separate analytic account fields (pre-16 pattern)Legacy databases predating analytic plansOne many2one per dimension instead of a JSON split; superseded by plans since 16

There is no drop-in alternative in core: this widget is the analytic distribution UI. The rows below are for the boundary cases, when what you actually need is a simpler relation or a plain percentage.

Frequently asked questions

What does the analytic_distribution widget do in Odoo?+
It renders and edits a line's analytic split: which analytic accounts carry the cost or revenue and at what percentage. The current split shows as tags, and a dropdown editor distributes the line across accounts with one column per applicable analytic plan. It is the widget behind the Analytic column on journal items, expenses and order lines.
Which field type does analytic_distribution need?+
In Odoo 19 the widget declares the json type, matching how core stores distributions on models like account.move.line. Odoo 18's source declared char and text instead, so custom models built on the old declaration should move to a Json field when upgrading.
How do I make the widget suggest the right distribution automatically?+
Two layers: configure distribution models in Accounting so recurring contexts get a split applied automatically, and wire the widget's product_field, account_field and amount_field options so it sees the line's context, the way core wires journal items. Users then only correct exceptions.
Can users save their own distribution templates?+
Yes, from the editor itself, and the source is specific about the shape of that feature: it opens account.analytic.distribution.model with creation enabled and in-place editing disabled, so users capture new templates but manage existing ones in Accounting configuration.
What is the difference between business_domain and business_domain_compute?+
Both feed the widget's account lookup context, but business_domain is an option inside options="{...}" while business_domain_compute is read from the field element's attributes, verified in extractProps. Setting the latter as an option silently does nothing, a classic copy-paste trap.
Why will percentages not accept more decimals?+
The widget fetches analytic_precision automatically through its field dependencies and rounds percentages against it. Raise the percentage decimal precision in Accounting settings; the widget follows.
Does analytic_distribution change in Odoo 20?+
On the public development branch the option surface, the json type and the dependencies are unchanged; the internals move to new components, including a rebuilt tag renderer and an offline plugin. XML views carry over as-is on current evidence. Odoo 20 ships around late September 2026, and we re-verify after release.

Analytic reports with an empty Unallocated column?

That takes distribution models tuned to your document flows, plans with the right applicability, and this widget wired with full context per view. We set up analytic accounting that people actually fill in, on Odoo 16 through 19.

Book a free consultation

How this page was produced

This page was verified by reading analytic_distribution.js in the Odoo 19.0 analytic module source: the descriptor with its eight options and json type, extractProps including the business_domain_compute attribute and the disable_save inversion, the analytic_precision dependency, and the create-only template wiring. The 18.0 branch of the same file was compared for the version table, and the Odoo 20 statement reflects a diff against the public development branch, clearly marked as unreleased. Spotted an error? Tell us and we will correct the page.