Skip to main content
iVentureTeam

receipt_selector

The small Invoice or Receipt toggle at the top of a journal entry. It rewrites its own labels, filters its own choices, and disappears entirely unless your database has sales receipts turned on.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated August 27, 20266 min read
Technical namereceipt_selector
Field typesselection
Viewsform
Moduleaccount, present wherever Invoicing or Accounting is installed
Used in core1 occurrence, the document type at the top of the journal entry form in account
VersionsOdoo 20.0, Odoo 19.0
No-code setupNo. It is tied to the journal entry document type and its session-level setting
Alternativesradio, radio_selection_with_filter, selection

What the receipt selector does

A journal entry in Odoo has a document type: customer invoice, vendor bill, credit note, refund, sales receipt, purchase receipt, or a plain entry. Most of those are decided by how you got to the form, and users never think about them. Two pairs are genuinely a choice: a vendor document can be a bill or a purchase receipt, and a customer document can be an invoice or a sales receipt.

This widget is what surfaces that choice, as a small pair of radio buttons above the document title. It starts from the standard radio widget and then does three things: it removes every value that is not one of the two relevant ones, it rewrites the two labels so the receipt option reads as Receipt rather than its longer technical name, and it decides whether the choice should appear at all.

When it should not appear, the widget renders the document type as plain text. That covers credit notes and refunds, read-only forms, and the common case of a database that never turned sales receipts on.

What this means for your team

The difference between an invoice and a receipt is not cosmetic. A receipt is used where payment happens at the point of sale and no credit is extended, which changes the accounting entries and, in several countries, the legal document requirements. Getting it right at document creation is far cheaper than reclassifying later.

What makes this widget worth understanding is the hiding rule, because it is the most common support question it generates. A finance user reads that Odoo supports sales receipts, opens a customer invoice, and sees no choice at all. The reason is a setting: outgoing documents only offer the receipt option when sales receipts are enabled for the database. Turn it on and the toggle appears.

The label rewriting is a small piece of interface craft worth copying. Both receipt values are shown simply as Receipt, because in the context of a document you already know is incoming or outgoing, the longer name adds nothing. The original label is kept for the read-only display, so the record still reads precisely when it is not being edited.

Supported options in Odoo 19

The widget declares no options of its own and its extractor simply delegates to the radio widget's, so the option below is inherited and works normally. Read from receipt_selector.js and the base radio field, Odoo 19.0.

OptionTypeWhat it does
horizontalbooleanInherited from the radio widget and honored, because the widget calls through to the base template. Core passes it so the two choices sit side by side.(default: false)

The filtering and the labels are hardcoded. The four document types the widget knows about, the two groups it sorts them into and the replacement labels are all written into the source. There is no option to add a third choice or to change what Receipt is called.

Working examples

The core usage

<field name="move_type"
       widget="receipt_selector"
       options="{'horizontal': true}"
       invisible="move_type == 'entry'"
       nolabel="1"
       readonly="state != 'draft'"/>

The read-only expression matters: once the entry leaves draft the widget renders the document type as text, which is the correct behavior for a posted document.

Why the choice is missing

<!-- outgoing documents only offer Receipt when the
     database has sales receipts enabled -->

The setting is read once per session through a lazy session value, so enabling it takes effect on the next page load rather than instantly.

The values it groups

in_invoice   # Bill
in_receipt   # Receipt
out_invoice  # Invoice
out_receipt  # Receipt

Everything else in the selection, including credit notes, refunds and plain entries, is left out of the radio group entirely.

Why an empty allow-list shows the full selection

The filtering happens in the items getter, and it is worth reading closely because it decides from the current value rather than from anything in the view. If the record's document type is one of the two incoming values, the allowed set is the incoming pair. If it is one of the two outgoing values and the session says sales receipts are enabled, the allowed set is the outgoing pair. In every other case the allowed set stays empty and the getter returns the selection untouched.

That last branch is easy to misread. An empty allowed set does not blank the radio group; it returns the full selection, and the template is what prevents the full list from being shown. The template renders radio buttons only when the field is editable, the value is not a credit note or refund, and, for outgoing documents, sales receipts are enabled. Otherwise it prints a span with the label.

The labels themselves are handled carefully. The widget deep-copies the selection before rewriting it, so the record's own field definition is left alone, and the read-only branch uses a separate getter that looks the label up in the original selection. That is why a posted vendor receipt reads with its full name while the editable radio next to a bill reads simply Receipt.

The session value is fetched through Odoo's lazy session service in the component's startup hook, with a callback that updates local state when it arrives. So on a slow first load the widget can briefly render the text branch before the radio group appears, which is harmless but explains an occasional flicker.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Behavior identical on the development branch; only props and state helpers change.
Odoo 19.0VerifiedFirst version. Verified against the shipped source.
Odoo 18.0Not availableWidget does not exist.
Odoo 17.0Not availableWidget does not exist.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. The widget is new in Odoo 19. Earlier versions did not offer this choice on the entry form at all, so there is nothing to migrate; a database upgraded from Odoo 18 gains the toggle with the standard accounting views. Custom journal entry forms that replaced the document type field should adopt the widget to keep the behavior.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The development branch is unstable and this may still change; we re-verify the page after release.

No behavior change. The development branch differs only in the migration to the new Owl props and reactive-state helpers. The document type groups, the label rewriting, the session lookup and the text fallback are identical, and core still uses the widget on the journal entry form.

Common problems and fixes

SymptomCause and fix
No Invoice or Receipt choice on a customer documentOutgoing documents only offer the receipt option when the database has sales receipts enabled. Enable sales receipts in the accounting settings, then reload the page.
The choice disappeared after postingThe core view makes the field read-only outside draft, and the widget renders text when read-only. Expected. Reset to draft if the document type genuinely has to change.
A credit note shows no choiceRefund and credit note types are excluded from the radio rendering by the template. Expected. There is no receipt equivalent for those documents.
The label says Receipt but the report says something longerThe widget rewrites labels only for the editable radio group; read-only displays and reports use the original selection label. Nothing to fix; this is deliberate.
The toggle flickers on loadThe sales receipts setting is fetched through a lazy session value after the first render. Harmless. It settles as soon as the value arrives.
I want a third document type in the groupThe four values and two groups are hardcoded in the widget. Use the plain radio widget, or the survey app's filtered radio widget, which takes its allow-list from a field.

Receipt selector vs the alternatives

WidgetBest forKey difference
receipt_selectorChoosing between an invoice and a receipt while a journal entry is still draftFilters the document type selection to the relevant pair, rewrites their labels, and falls back to plain text
radioAny ordinary short choice listShows every value with its declared label and never hides itself
radio_selection_with_filterThe same filtering idea driven by dataTakes its allow-list from a field on the record instead of hardcoding values
selectionLonger choice listsDropdown rendering with no filtering or relabeling

On any other selection field, the plain radio widget is the right choice and behaves predictably. This one is bound to the journal entry document type by its hardcoded value groups. If you need the same idea elsewhere, the filtered radio widget in the Survey app takes its allow-list from a field on the record and is the reusable version of this pattern.

Frequently asked questions

Why is there no Receipt option on my customer invoices?+
Outgoing documents only offer it when the database has sales receipts enabled. The widget reads that setting from a lazily loaded session value, so turning it on takes effect on the next page load.
Which document types does it switch between?+
Two pairs, hardcoded: vendor bill with purchase receipt, and customer invoice with sales receipt. Credit notes, refunds and plain entries are excluded.
Why does it sometimes show plain text?+
The template renders text rather than radio buttons when the field is read-only, when the document is a credit note or refund, and for outgoing documents when sales receipts are not enabled.
Why does the label say just Receipt?+
The widget deep-copies the selection and rewrites the two receipt labels for the editable radio group only. The read-only display uses the original label, so nothing else in Odoo is affected.
Can I reuse it for another selection?+
Not usefully. The four document types and their grouping are written into the source. The survey app's filtered radio widget is the reusable version of this idea.

Invoices, receipts and the accounting behind both

Document types decide which entries Odoo posts and which legal documents you can issue, and the right setup depends on your country and how you take payment. We configure Odoo Accounting and the localization that goes with it, on versions 16 through 19.

Book a free consultation

How this page was produced

The value groups, the label rewriting, the session lookup and the conditions under which the widget renders text rather than radio buttons were read from receipt_selector.js and its template on the Odoo 19.0 branch, with the usage taken from account/views/account_move_views.xml. Version coverage comes from the absence of the file on 16.0, 17.0 and 18.0, and the Odoo 20 notes from a full comparison against the public development branch. Spotted an error? Tell us and we will correct the page.