Purchase Order Line Import
This module adds an Import Lines button to requests for quotation. It opens a wizard that reads a spreadsheet (XLSX, XLS, ODS or CSV) and adds one purchase order line per row to the current request for quotation.
The spreadsheet supports these columns:
Column |
Required |
Purchase order line field |
|---|---|---|
Internal Reference |
Yes |
product_id, by the product internal reference |
Quantity |
Yes |
product_qty |
Description |
No |
name |
Unit Price |
No |
price_unit |
Analytic Account |
No |
analytic_distribution, 100% to the account |
An empty optional cell keeps the value Odoo computes for the line: the default description of the product and the vendor price. The analytic account is searched by code or by name.
All the rows are checked before any line is created: if any of them has an error, nothing is imported and every error is reported with its row number.
Table of contents
Usage
Open a request for quotation in the RFQ or RFQ Sent state.
Click Import Lines.
Click Download Template to get an empty spreadsheet with the supported columns. The required columns are highlighted, and each header has a comment that describes it.
Fill in one row per line, upload the file and click Import.
The first row of the file must hold the column names. A column is recognized by its name in the language of the user, in English, or by its technical key (default_code, product_qty, name, price_unit, analytic_account), regardless of the case. The order of the columns does not matter.
The imported lines are added after the existing ones, and a message on the order records the file they come from.
Development
The wizard purchase.order.line.import is built to be extended. Each row of the file reaches the hooks as a dictionary that maps the column keys to the cell values, already stripped, and only holds the columns present in the file. A hook that raises a UserError reports its message as the error of that row, and the import goes on checking the next rows.
_get_import_columns(): the columns the file accepts. Each one is a dictionary with key, label, help and required.
_prepare_order_line_vals(row): the values of the purchase order line created for a row.
_create_order_lines(vals_list): creates the lines of all the rows once every row is valid, after the existing lines of the order.
_get_product_domain(row) and _get_product(row): the search of the product of a row.
_get_product_qty(row): the quantity of a row.
_get_analytic_account_domain(row) and _get_analytic_distribution(row): the search of the analytic account of a row, and the analytic distribution it gives.
_parse_float(value, label): converts a cell to a number, with the separators inferred by base_import.
A new column is added by extending _get_import_columns(), and its value is used in _prepare_order_line_vals(). It is then part of the downloaded template and recognized in the uploaded files, by its label or by its key:
from odoo import _, models
class PurchaseOrderLineImport(models.TransientModel):
_inherit = "purchase.order.line.import"
def _get_import_columns(self):
columns = super()._get_import_columns()
columns.append(
{
"key": "discount",
"label": _("Discount"),
"help": _("Discount in %."),
"required": False,
}
)
return columns
def _prepare_order_line_vals(self, row):
vals = super()._prepare_order_line_vals(row)
if row.get("discount"):
vals["discount"] = self._parse_float(row["discount"], _("Discount"))
return vals
The search of an existing column is changed through its domain method, for instance to accept only the products the vendor of the order sells:
def _get_product_domain(self, row):
domain = super()._get_product_domain(row)
partner = self.order_id.partner_id.commercial_partner_id
return domain + [("seller_ids.partner_id", "=", partner.id)]
Bug Tracker
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed feedback.
Do not contact contributors directly about support or help with technical issues.
Credits
Contributors
-
Andreu Orensanz <andreu.orensanz@forgeflow.com>
Maintainers
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.
This module is part of the OCA/purchase-workflow project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
Metadata
Release files for odoo-addon-purchase-order-line-import-sheet-file 17.0.1.0.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| odoo_addon_purchase_order_line_import_sheet_file-17.0.1.0.0.3-py3-none-any.whl | Python 3 | none | any | Details for odoo_addon_purchase_order_line_import_sheet_file-17.0.1.0.0.3-py3-none-any.whl |
Release files / odoo_addon_purchase_order_line_import_sheet_file-17.0.1.0.0.3-py3-none-any.whl
| Download URL | odoo_addon_purchase_order_line_import_sheet_file-17.0.1.0.0.3-py3-none-any.whl |
|---|---|
| Size | 43.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1f1107ef01250ff57de03cae7c07795f12e8d0033a271c189a8eac241d66a8da
|
|
BLAKE2b-256 checksum How to use checksums |
e5829d6c872615c4175ddd376e896a0fc6359620c858ea00c34ffc53153d838d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Security for odoo-addon-purchase-order-line-import-sheet-file 17.0.1.0.0.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.