Skip to main content
iVentureTeam

l10n_ro_edi_stock_document_state

Romania's e-Transport replies can be one error or ten. l10n_ro_edi_stock_document_state takes Odoo's document state widget and reformats the popover: single messages stay plain, multiple errors become a bulleted list.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 25, 2026Updated August 25, 20265 min read
Technical namel10n_ro_edi_stock_document_state
Field typesselection, many2one
Viewslist (embedded e-Transport document lists)
Modulel10n_ro_edi_stock (Romania e-Transport)
Used in core2 occurrences across 2 modules: l10n_ro_edi_stock, l10n_ro_edi_stock_batch
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0
No-code setupNo. Ships preconfigured on the e-Transport document lists
Alternativesaccount_document_state, selection, selection_badge

What the e-Transport state field does

Romanian transporters declare goods movements to ANAF's e-Transport platform, and each declaration lives in Odoo as a document record on the transfer: a state, a UIT code, a timestamp and a message holding whatever the government API answered. This widget renders that state column on the document lists.

It is deliberately tiny. The class extends DocumentState from the account module and overrides a single getter, the one that feeds the popover. Where the parent shows message verbatim, this subclass splits the text on newlines, throws away blank lines, and then chooses a format: exactly one surviving line is shown as-is, while two or more are each prefixed with a bullet and rejoined, so a batch of ANAF validation errors reads as a list instead of a wall of text.

Everything else, the info icon that appears only when a message exists, the top-anchored popover, the clipboard button, the selection rendering underneath, is inherited untouched, which also means the companion field contract is unchanged: the view must load a field literally named message.

What this means for your team

e-Transport declarations fail in clusters: a missing net weight, an invalid location code and a bad vehicle plate arrive as one multi-line rejection. For the logistics clerk fixing the transfer, the difference between a bulleted list of three problems and a run-on paragraph is whether the second and third errors get fixed before the retry. UIT codes are legally required on transport documents, so unresolved rejections hold trucks, not just records.

The pattern generalizes: whenever an external system returns several errors in one response, a subclass overriding just the message getter is the cheapest way to make them readable. This widget is the canonical core example of doing exactly that, thirteen lines of real code on top of the shared document state machinery.

Supported options in Odoo 19

No options of its own; the surface below is inherited from the spread selection descriptor, and the real configuration remains the implicit contract shared with the parent widget: a loaded message field on the record.

OptionTypeWhat it does
placeholder_fieldfield name (inherited, dead)Comes with the spread selection descriptor and is never read by its extractProps; setting it does nothing. Listed only to document the inherited surface honestly.(since Odoo 19.0)

Both core lists already load the message column invisibly, so the popover works out of the box, unlike the E-Factura list documented on the parent widget's page. If you inherit these views and rebuild the list, keep the column_invisible="1" message field or the icon disappears.

Working examples

The core usage, from the batch transfer form

<list>
    <field name="message" column_invisible="1"/>
    <field name="datetime"/>
    <field name="state" string="Status"
           widget="l10n_ro_edi_stock_document_state"/>
    <field name="l10n_ro_edi_stock_uit" string="UIT"/>
</list>

State and UIT side by side, message loaded invisibly for the popover.

Reusing the bullet trick on your own integration

import { DocumentState } from "@account/components/document_state/document_state_field";

class MyApiState extends DocumentState {
    get message() { // reformat this.props.record.data.message }
}

Exactly the pattern this widget demonstrates: inherit the machinery, override only the text.

Thirteen lines, read closely

The getter is defensive in a way worth copying. Every step uses optional chaining, split, filter, map, join, so a record with no message, an empty string or whitespace-only lines degrades to an empty result instead of a crash, and the inherited template then simply skips the icon. The filter also trims each line before length-checking it, which quietly swallows the trailing newline ANAF responses tend to carry.

Two inherited behaviors read differently in this context. The popover copies the reformatted text, bullets included, because the clipboard handler reads the same getter, so what you paste into a ticket matches what you saw. And since the subclass keeps the parent's static template reference, there is no template file in l10n_ro_edi_stock at all: the module ships one JS file for the whole widget, a useful reminder that a widget is a descriptor, not necessarily markup.

Related and easy to confuse: the plain l10n_ro_edi module handles E-Factura invoices with the parent widget directly, while this one covers e-Transport on stock pickings and batches. Same state machinery, different government API, different module.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Byte-identical on the development branch; see below.
Odoo 19.0VerifiedVerified against the shipped source; unchanged since 17.
Odoo 18.0VerifiedSame file and behavior.
Odoo 17.0VerifiedIntroduced with the e-Transport document flow.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. Nothing changes across 17, 18 and 19. Inherited views keep working; only keep the invisible message column when customizing the lists.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. We compared the widget on the public development branch at the time of writing, with the standard caveat about unreleased branches.

Byte-identical to 19, and its parent widget in account is unchanged too, so the whole chain carries over. We re-verify once Odoo 20 ships.

Common problems and fixes

SymptomCause and fix
No info icon next to a failed declarationA customized list dropped the invisible message column the widget reads. Restore <field name="message" column_invisible="1"/> in the embedded list.
Errors show as one bullet with everything glued togetherThe API response arrived without newlines, so the splitter sees a single line. Expected: the widget only bullets what arrives as separate lines.
Copied text contains bullet charactersThe clipboard reads the same reformatted getter the popover shows. Expected behavior; strip the bullets after pasting if a system needs raw text.
Widget missing on a database without the Romanian localizationThe registration ships in l10n_ro_edi_stock; other databases log Missing widget and fall back to plain selection. Install the module, or use account_document_state outside Romania.
State renders but popover is emptyThe message contains only whitespace lines; the filter removes them all. Nothing to fix client side; check what the server stored in message.

E-Transport state field vs the alternatives

WidgetBest forKey difference
l10n_ro_edi_stock_document_stateRomanian e-Transport statuses whose rejections arrive as multi-line ANAF errorsInherits the document state popover and reformats multi-line messages into bullets
account_document_stateAny e-invoicing or integration status with a verbatim message popoverThe parent widget: same icon and popover, no line splitting or bullets
selectionPlain selection display without message affordancesNo icon, no popover, no companion field contract
selection_badgeLouder visual status as colored badgesEmphasis over explanation; error texts stay out of reach

Within the family: the parent widget for verbatim messages, this one for line-per-error responses. Outside it, plain selection widgets drop the popover entirely.

Frequently asked questions

What is the UIT shown next to the state?+
The unique transport code ANAF issues per declared movement; drivers must carry it. The state column this widget renders tells you whether that code was obtained, and the popover explains failures.
When do I get bullets instead of plain text?+
Whenever the stored message contains more than one non-empty line after splitting on line breaks. One line renders bare; several become "• " entries, one per line.
Does this widget also cover Romanian E-Factura invoices?+
No. Invoices use the parent account_document_state widget in the l10n_ro_edi module; this subclass belongs to the e-Transport stock modules and their picking and batch lists.
Can I point the popover at a different field than message?+
Not with options; the field name is hardcoded up the inheritance chain. Subclass and override the message getter, which is precisely how this widget customizes its parent.
Why does my custom list show the state but nothing else?+
The widget needs the message field loaded in the same view to decide whether to render the icon. Core loads it as an invisible column; a rebuilt list must do the same.

Trucks waiting on UIT codes and cryptic ANAF replies?

We integrate Odoo with government platforms across Europe, e-Transport and E-Factura included: reliable submissions, readable errors and retry flows your logistics team can run without a developer on call.

Book a free consultation

How this page was produced

Verified by reading document_state_field.js in the Odoo 19.0 l10n_ro_edi_stock module, its parent in account, and both core list usages with their invisible message columns. Branch checks cover 17.0 through the development branch, all byte-identical. Spotted an error? Tell us and we will correct the page.