Skip to main content
Odoo Community Association

Purchase Order Line Import

Beta License: AGPL-3 OCA/purchase-workflow Translate me on Weblate Try me on Runboat

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

  1. Open a request for quotation in the RFQ or RFQ Sent state.

  2. Click Import Lines.

  3. 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.

  4. 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

Authors

  • ForgeFlow

Contributors

Maintainers

This module is maintained by the OCA.

Odoo Community Association

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)

Table of built distributions (wheels) for odoo-addon-purchase-order-line-import-sheet-file 17.0.1.0.0.3
File Interpreter ABI Platform Actions
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page