Skip to main content
iVentureTeam

purchase_file_uploader

Upload a bill against one purchase order or a selection of them, with a check that they all belong to the same vendor.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated August 29, 20264 min read
Technical namepurchase_file_uploader
Viewslist, form (view widget, <widget> element)
Modulepurchase, the Purchase app
Used in corePurchase order lists and forms in purchase
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0
No-code setupNo. It is set in view XML and depends on module-specific data
Alternativesbill_upload_guide, attach_document, many2many_binary

What the PO bill uploader does

A vendor bill usually arrives as a file, and it usually relates to one or more purchase orders you already have. Creating the bill by hand and then matching it back is the slow path.

This widget is the fast one. Drop the file where the purchase orders are, and the server creates the bill against them with the file attached.

It works in two positions. On a single order it targets that order. In a list it targets the current selection, provided every selected order belongs to the same vendor.

What this means for your team

Three-way matching, order to receipt to bill, is what stops overbilling, and it only happens if the bill is created from the order rather than beside it. Making that the path of least resistance is the whole point of this control.

The single vendor rule reflects a real constraint: a bill belongs to one vendor. Teams that batch scan supplier post should sort by vendor before uploading, which is worth saying explicitly in a process document.

Supported options in Odoo 19

The widget takes the standard view widget props plus two optional props, a record and a list, which is how it serves both positions. What it does with them is described below. Read from the purchase file uploader source, Odoo 19.0.

OptionTypeWhat it does
recordoptional propWhen present, the bill targets that single purchase order.
listoptional propWhen no record is present, the bill targets the list's selected identifiers.
the vendor checklist-only guardRefuses with a validation dialog when the selection spans more than one vendor.
action_create_invoiceserver callReceives the target identifiers and every collected attachment identifier together.

The vendor check only runs in a list. The handler returns immediately unless the current view is a list, because a single order cannot span vendors.

Working examples

Placing it

<widget name="purchase_file_uploader"/>

Works on both the list and the form.

What it targets

a record prop  -> that order
otherwise      -> the list's selected ids

Resolved at upload time.

The vendor rule

# more than one vendor in the selection
# -> a validation dialog, and nothing uploads

A bill belongs to one vendor.

Two phases, and the finally block that matters

The upload happens in two phases, and the split matters.

Each file is first created as an attachment on its own, with its name, type and content, using the current search context. The resulting identifier is pushed onto a list held on the component.

Only when every file has finished does the second phase run: one server call to create the invoice, passing both the target order identifiers and all the collected attachment identifiers together. One bill from several files, rather than several bills.

That collected list is cleared in a finally block wrapped around the creation call, which is the detail worth copying. Without it, a failed creation would leave stale attachment identifiers on the component and the next upload would silently include them.

Target resolution is the other half. With a record prop the widget uses that record's identifier; otherwise it asks the list for its selected identifiers. The same two-branch pattern appears in the getter that exposes the records themselves.

Version compatibility

VersionStatusNotes
Odoo 20.0Partial / changedNot released. The attachment payload key changes from data to raw.
Odoo 19.0VerifiedVerified against the shipped source.
Odoo 18.0VerifiedSame two-phase upload and vendor check.
Odoo 17.0VerifiedSame approach with older component conventions.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. Present since Odoo 17. The two-phase upload and the single vendor rule have been stable across those versions.

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 this page after the release.

The attachment payload key changes. The development branch writes the file content under the raw key rather than the data key when creating the attachment. Everything else, including the vendor check and the finally block, is unchanged.

Common problems and fixes

SymptomCause and fix
A validation dialog about a single vendorThe list selection spans more than one vendor. Select orders from one vendor at a time.
Several files produced one billAll attachment identifiers are passed to a single creation call. Expected. Upload separately for separate bills.
Nothing happens on a formThe vendor check returns early outside a list, so the upload should proceed. Check the record prop is reaching the widget.
An old attachment appears on a new billIt should not; the collected list is cleared in a finally block. Reload the view if a customization interfered.
The created bill is emptyThe server could not read the attachment content. Check the file type is one the digitization supports.
The widget is missingThe Purchase module is not installed in that database. Install Purchase.

PO bill uploader vs the alternatives

WidgetBest forKey difference
purchase_file_uploaderCreating a vendor bill from a file against one or more purchase ordersWorks from a record or a list selection, with a single vendor rule and a clean-up on failure
bill_upload_guideThe first bill, from the accounting sideGuidance and three paths rather than order matching
attach_documentAttaching a file to a recordNo bill is created
many2many_binaryA set of attachments on a recordStorage rather than an action

The bill upload guide covers the same ground from the accounting side, without a purchase order to match against. Attaching a file to an existing bill is the right move when the bill already exists.

Frequently asked questions

Can I upload against several purchase orders?+
Yes, from a list, provided every selected order belongs to the same vendor. A bill belongs to one vendor, so a mixed selection is refused.
Do several files make several bills?+
No. Every file becomes an attachment first, then a single creation call receives all of them, producing one bill.
What happens if the creation fails?+
The collected attachment identifiers are cleared in a finally block, so a retry does not silently include them again.
How does it know what to target?+
Two optional props. With a record it uses that order; otherwise it asks the list for its selected identifiers.
What changes in Odoo 20?+
The attachment content is written under a different payload key on the development branch. Nothing else changes.

Purchase to pay that matches itself

Three-way matching only works when bills are created from orders rather than beside them. We implement Odoo Purchase and Accounting so the match happens automatically, on versions 16 through 19.

Book a free consultation

How this page was produced

The two optional props and the branches that use them, the list-only vendor check, the per-file attachment creation, the single invoice creation call with all collected identifiers and the finally block clearing them were read from the purchase file uploader source on the Odoo 19.0 branch. Version coverage comes from comparing the file across the 17.0 and 18.0 branches and its absence on 16.0, plus a comparison against the public development branch. Spotted an error? Tell us and we will correct the page.