Skip to main content
iVentureTeam

account_document_state

Government e-invoicing replies rarely fit in a status column. account_document_state renders the selection state and, whenever the record carries a message, adds an info icon whose popover shows the full text with a copy button.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 25, 2026Updated August 25, 20265 min read
Technical nameaccount_document_state
Field typesselection, many2one
Viewslist (embedded e-invoicing document lists)
Moduleaccount (Invoicing)
Used in core2 occurrences across 2 modules: l10n_gr_edi, l10n_ro_edi
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0
No-code setupNo. Applied in view XML together with an invisible message column
Alternativesselection, selection_badge, state_selection

What the document state field does

Electronic invoicing flows, Greece's myDATA, Romania's E-Factura and friends, track each submission in a document record with a state selection and a free-text message holding whatever the government API answered. This widget displays both without spending two columns.

It extends the standard selection field, so the state itself renders unchanged: the label of the current selection value, with whatever row decorations the list adds. The subclass contributes one thing, an fa-info-circle anchor rendered after the value whenever the record's message field holds text. Clicking it opens a popover anchored to the icon, positioned above, that prints the message with line breaks preserved and offers a clipboard button; copying shows a Text copied toast and closes the popover, and clicking the icon again toggles it shut.

Registration spreads the base selectionField descriptor with only the component swapped, which is why everything about the selection behavior, including its quirks, carries over verbatim.

What this means for your team

When a tax authority rejects an invoice, the difference between a cryptic Failed state and the actual error text is a support ticket versus a self-service fix. This widget keeps the rejection reason one click from the status, and the copy button exists for exactly the workflow you expect: paste the raw government error into a search, a helpdesk ticket or an email to the accountant.

The pattern is just as useful outside localizations. Any custom integration that records a status plus a response payload, payment gateways, EDI bridges, shipping APIs, can reuse this widget as-is on its own document model: name the text field message, load it invisibly next to the state, done.

Supported options in Odoo 19

The widget adds no options of its own. The inherited declaration from the base selection descriptor is listed below for completeness, along with the implicit contract that actually configures the widget: the hardcoded companion field.

OptionTypeWhat it does
placeholder_fieldfield name (inherited, dead)Declared by the base selection descriptor this widget spreads, but the base extractProps never reads it, so setting it does nothing. Listed to keep the inherited surface honest.(since Odoo 19.0)

The message must be loaded, not just exist. The widget reads record.data.message and declares no fieldDependencies, so a list that omits the column shows a bare state forever. Core's own views demonstrate both outcomes: myDATA and e-Transport load <field name="message" column_invisible="1"/>, while the 19.0 E-Factura list does not, and its icon consequently never appears.

Working examples

The full pattern, from the myDATA documents list

<list>
    <field name="message" column_invisible="1"/>
    <field name="datetime"/>
    <field name="state" widget="account_document_state"/>
</list>

The invisible column is the load trigger; without it the widget has no message to show.

On a custom integration log model

state = fields.Selection([...])
message = fields.Char(readonly=True)  # the name is the contract

Any model with this pair can use the widget; the field must be named message, nothing else is read.

Popover mechanics and an unloaded message in core

The popover mechanics are small but deliberate. The component keeps the popover's close function on itself: clicking the icon while open closes it, so the icon is a true toggle rather than a stacker. The popover mounts with closeOnClickAway and position: "top", prints the message inside a white-space: pre-wrap span so multi-line government responses keep their formatting, and the copy button writes the raw message to navigator.clipboard, which quietly requires a secure context, HTTPS or localhost, to function.

The inheritance detail worth knowing: because the descriptor spreads selectionField, the widget also inherits selection's extractProps, which enables autosave in kanban cards, and its declared placeholder_field option, which the base extractProps never reads, a dead declaration this page's sibling selection page documents. Neither matters in the embedded readonly lists core uses, but both travel with the widget if you deploy it elsewhere.

And the core inconsistency, verified in 19.0 and still present on the development branch: l10n_ro_edi's E-Factura documents list applies the widget without loading message, so Romanian invoice errors are only reachable through the move's message history, not the popover. The Romanian e-Transport modules, which subclass this widget, do load it correctly.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Byte-identical on the development branch; see below.
Odoo 19.0VerifiedVerified against the shipped source; unchanged from 17.
Odoo 18.0VerifiedSame component and behavior.
Odoo 17.0VerifiedIntroduced here alongside the e-invoicing document models.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. Nothing changes between 17, 18 and 19; views and custom usages carry over untouched. Databases upgraded from 16 gain the widget with whichever localization module ships it.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. We compared the widget's file on the public development branch at the time of writing, with the usual caveat that the branch is unstable until release.

Byte-identical to 19: component, popover and registration are unchanged, and the base selection descriptor it spreads is also unchanged for this widget's purposes. Even the unloaded message in the E-Factura list is still there. We re-verify once Odoo 20 ships.

Common problems and fixes

SymptomCause and fix
No info icon although the document has an errorThe message field is not loaded in the view; the widget reads record.data.message with no declared dependencies. Add <field name="message" column_invisible="1"/> to the list, the fix the E-Factura list itself needs.
Copy button does nothingnavigator.clipboard requires a secure context. Serve Odoo over HTTPS (or use localhost in development).
Popover opens above and gets clipped in a short listThe position is hardcoded to top. Accept the flip the popover service applies, or subclass with a different position.
Message shows as one long line elsewhereOnly the popover preserves line breaks; other renderings of the field do not. Read the message through the widget's popover, or format it in a custom view.
State column stops being editableCore's embedded lists set edit and create to false; the widget itself does not force readonly. Expected in the localization lists; on custom views the selection stays editable.

Document state field vs the alternatives

WidgetBest forKey difference
account_document_stateStatus columns that carry a server or government response worth readingSelection rendering plus a popover fed by a hardcoded message field, with clipboard copy
selectionPlain editable selection fieldsNo icon, no popover; this widget is the base plus the message affordance
selection_badgeSelection rendered as clickable colored badgesStronger visual state but no path to an explanation text
state_selectionThe three-dot kanban state with quick switchingA different interaction model entirely; no message display

Use this widget when a status needs its explanation attached. If the status only needs to look stronger, badges do that; if the user must edit the status, stay with the plain selection family.

Frequently asked questions

Which field feeds the popover?+
A field literally named message on the same record. The name is hardcoded in the component's getter, and no option exists to point it elsewhere; subclassing is the only way to change the source, which is what the Romanian e-Transport widget does to reformat it.
Why does the Greek list show the icon but the Romanian E-Factura list never does?+
The myDATA list loads message as an invisible column and the E-Factura list does not, so the widget has nothing to read there. That is a core view gap in 19, still present on the development branch, and a one-line inherited view fixes it on your database.
Can I use account_document_state on my own model?+
Yes. It needs a selection field to sit on and a char or text field named message loaded in the same view. Integration log models are the natural fit.
Does the widget work in form views?+
Yes, the selection renders normally and the icon logic is identical. Core only uses it in embedded lists because that is where e-invoicing documents live.
Is the message stripped or truncated in the popover?+
No. The raw field value is rendered with pre-wrap, so line breaks survive, and the copy button copies exactly that raw text.

E-invoicing mandates keeping your finance team guessing?

myDATA, E-Factura, PEPPOL: every mandate has its own states, errors and deadlines. Our Odoo consultants set up compliant e-invoicing flows and make rejection reasons readable where your team works, not buried in government portals.

Book a free consultation

How this page was produced

Verified by reading document_state_field.js, its popover template and the spread selection descriptor in the Odoo 19.0 account module, plus every core view using the widget in l10n_gr_edi and l10n_ro_edi, where the unloaded message column was confirmed field by field. Branch diffs cover 17.0 through the development branch. Spotted an error? Tell us and we will correct the page.